594 lines
18 KiB
Plaintext
594 lines
18 KiB
Plaintext
NOTE: this file is a bad copy from an HTML-formatted page.
|
|
|
|
What it is: A library and syntax language for structure-centric world/map generation. But what is "structure-centric", you ask? Easy, I'll explain!
|
|
|
|
Structures can be thought of as complex collections of entities/cells. From this, structures can be made up of other structures to increase the variation and complexity needed for a structure. Examples of structures are: castles, moats, ravines, towns, rooms, and much more.
|
|
|
|
Towards the end of (easily?) creating complicated maps, I've created this structure generation syntax and library/codebase written in C.
|
|
|
|
Also, you can make weird faces in it:
|
|
|
|
...............1...........1............
|
|
.............11111......1111111.........
|
|
............1111011....111101111........
|
|
...........111000001..11100000111.......
|
|
............1111011....111101111........
|
|
.............11111......1111111.........
|
|
...............1...........1............
|
|
........................................
|
|
........................................
|
|
......0.................................
|
|
......000000000000000..............0....
|
|
.......0...0.0...0.00000000000000000....
|
|
........................00....0..00.....
|
|
|
|
|
|
Syntax
|
|
Basic Syntax
|
|
|
|
As it stands, structures are written in plain text files with very simple formatting rules. To begin with, a structures file can contain an (unlimited) amount of structures within it. Each structure can have various settings applied that alters the generation behaviors. The basic variable settings are:
|
|
flags -- defines the generation behavior using bitflags. Multiple flags can be set by piping them together (ex. "flags CIRCLE|BORDER|ORIGIN")
|
|
|
|
Shape Generation
|
|
CIRCLE - Bresenham-like ellipse generation
|
|
RECT - basic "box" generation
|
|
|
|
Shape Modification
|
|
BORDER - creates an interior border using the current shape
|
|
IGNORE_EMPTY - ignores cells that are empty (i.e., have no id_s written to them)
|
|
|
|
Structure Placement
|
|
ORIGIN - places the structure from its center
|
|
OVERLAP - overlaps the structure on top of other potential structures
|
|
|
|
size_x, size_y -- defines the size of the structure. Values may be: single numbers(e.g., "size_x 4"), percentages(e.g., "size_x 50%" of parent's size), and ranges of either(e.g., "size_x 25%~50%"). If omitted, defaults to 0, 0
|
|
x, y -- defines the position of the structure. Values may be: single numbers(e.g., "x -4", "x 4"), percentages(e.g., "x -50%", "x 50%"), and ranges of either(e.g., "x -50%~50%"). If omitted, defaults to 0, 0
|
|
id_1 -- first id of the structure. Values may be: single numbers(e.g., "id_1 2"), ranges(e.g., "id_1 1~4"), or comma-delimited sets of either(e.g., "id_1 2, 1~4")
|
|
id_2 -- second id of the structure. Follows same rules as id_1
|
|
|
|
Before delving into more complicated aspects of structure definitions, let us use some of the above information to create a simple structure.
|
|
A Simple Circle
|
|
|
|
A rudimentary example that creates a variable-sized tower in the middle of the screen would be:
|
|
|
|
tower {
|
|
flags CIRCLE
|
|
size_x 12~16
|
|
size_y 9~14
|
|
id_1 0
|
|
}
|
|
|
|
This would generate structures similar to the following:
|
|
|
|
........................................
|
|
....................0...................
|
|
.................0000000................
|
|
................000000000...............
|
|
...............00000000000..............
|
|
...............00000000000..............
|
|
..............0000000000000.............
|
|
...............00000000000..............
|
|
...............00000000000..............
|
|
................000000000...............
|
|
.................0000000................
|
|
....................0...................
|
|
........................................
|
|
|
|
Complex Syntax: Relations
|
|
|
|
Every structure can have 3 additional sets of information. The first I will cover is relations. A relation is, as the name implies, a relationship to another structure. In general, relations are used to create sub-structures within a structure.
|
|
|
|
Relations are contained with a relations block, and each relation is defined in a similar method as a regular structure. Acceptable settings are:
|
|
|
|
flags -- same as structure flags, but override and/or stack on top of the given structure's flags
|
|
x, y -- override position settings
|
|
count -- defines how many times to generate this relation. Values may be: single numbers(e.g., "count 2") or ranges(e.g., "count 2~6"). If omitted, defaults to 1.
|
|
|
|
Using this new information, let us expand upon the earlier tower.
|
|
A Simple Tower
|
|
|
|
An ellipse by itself is rather boring, but we can spice things up by using relations to create walls:
|
|
|
|
tower {
|
|
flags CIRCLE
|
|
size_x 12~16
|
|
size_y 9~14
|
|
id_1 0
|
|
relations {
|
|
tower_walls {
|
|
flags CIRCLE|OVERLAP
|
|
}
|
|
}
|
|
}
|
|
tower_walls {
|
|
flags BORDER
|
|
size_x 100%
|
|
size_y 100%
|
|
id_1 1
|
|
}
|
|
|
|
This would generate a structure similar to the following:
|
|
|
|
........................................
|
|
...................1....................
|
|
................1111111.................
|
|
..............11100000111...............
|
|
..............10000000001...............
|
|
.............1100000000011..............
|
|
..............10000000001...............
|
|
..............11100000111...............
|
|
................1111111.................
|
|
...................1....................
|
|
........................................
|
|
|
|
Complex Syntax: Replace
|
|
|
|
With the concept of relations out of the way, we can move into the replace functionality. For this example, we're going to use another structure to remove a section of walls from the tower.
|
|
|
|
tower {
|
|
flags CIRCLE
|
|
size_x 12~16
|
|
size_y 9~14
|
|
id_1 0
|
|
relations {
|
|
tower_walls {
|
|
flags CIRCLE|BORDER|OVERLAP
|
|
}
|
|
hole {
|
|
x 50%
|
|
y 50%
|
|
}
|
|
}
|
|
}
|
|
tower_walls {
|
|
flags BORDER
|
|
size_x 100%
|
|
size_y 100%
|
|
id_1 1
|
|
}
|
|
hole {
|
|
flags RECT|IGNORE_EMPTY
|
|
size_x 100%
|
|
id_1 0
|
|
replace {
|
|
id_1 1
|
|
}
|
|
}
|
|
|
|
All we've done is create a new "hole" structure that replaces any overlapping cell with an id_1 of "1" with "0". We've added this structure as a relation to the tower so that it is applied appropriately. The IGNORE_EMPTY flag is only used to prevent the replacement of empty (unset) tiles.
|
|
|
|
The resulting replacement would generate something similar to:
|
|
|
|
........................................
|
|
...................1....................
|
|
................1111111.................
|
|
..............11100000111...............
|
|
..............10000000001...............
|
|
.............1100000000000..............
|
|
..............10000000000...............
|
|
..............11100000000...............
|
|
................1111000.................
|
|
...................1....................
|
|
........................................
|
|
|
|
Complex Syntax: Paths
|
|
|
|
The (currently!) final important structure generating concept is that of paths. The first key concept is to realize that paths are generated in a separate pass from initial structures. During structure generation, structures are built and then recorded as "live structures". After this, these live structures are checked for any pathing configuration, and if found, a pathing pass is made. The pathing pass itself generates new live structures for every path "step" made (kept separately from the previous!) and handles the building as per normal operations.
|
|
|
|
A path is a configuration within a structure that defines some form of pathing behavior. This includes from/to destination structures, position offsets, structure to use for pathing, pathing algorithm, and others. Acceptable settings for a path are:
|
|
|
|
flags -- these define the behaviors of the pathing
|
|
Algorithms/Movement
|
|
DUMB -- doggedly move towards "to" by incrementing or decrementing x and y position. Is stopped by cells that cannot be replaced and are not empty.
|
|
A* -- uses A* to intelligently move towards position (NOT IMPLEMENTED (YET!))
|
|
WALK -- only move one cell in one direction at a time (e.g., x+1 OR y+1, not both)
|
|
WANDER -- some odd chance to randomly move x or y in a direction. Requires an Algorithm.
|
|
|
|
Looping
|
|
ALL -- attempt to path find to all targets that match the to pathing syntax
|
|
|
|
Etc.
|
|
FORCE -- if pathing movement fails too many times(>32), force movement anyway
|
|
UNIQUE -- only look for from/to targets that have not been pathed to/from by this structure
|
|
|
|
to -- pathing syntax for the structure to path to - REQUIRED
|
|
to_flags -- flags that define a specific "to" behavior
|
|
ORIGIN -- you guessed it, to_x/to_y values are relative to the center of the target
|
|
|
|
to_x, to_y -- position to path to. Values may be: single numbers(e.g., "1", "-1"), percentages(e.g., "25%"), ranges(e.g., "-25%~25%", "-5~5"), and sets of any(e.g., "1, 25%, -5~5")
|
|
from -- pathing syntax for the structure to path from. If omitted, defaults to the structure making this path.
|
|
from_flags -- same as to_flags
|
|
from_x, from_y -- same as to_x, to_y
|
|
x, y -- positional data that is applied to each pathing step. Values may be: single numbers(e.g., "-1"), ranges(e.g., "-1~1"), or sets of either(e.g., "-1, -1~1")
|
|
|
|
Pathing Syntax
|
|
|
|
Pathing syntax, used for to and from in pathing, refers to live structures and uses a straight-forward syntax contained in a single string. An example pathing syntax string could be: ":tower:hole" The following are the single-character "commands" used to acquire a live structure.
|
|
|
|
: -- if the first character of the string, get the global "root" live structure
|
|
: -- otherwise it is used a position delimiter to specify parent->child
|
|
^ -- get parent of this context's live structure
|
|
|
|
These can be combined to acquire live structures in complex structures. Examples:
|
|
|
|
"tower" -- look for a structure named "tower" in the current context.
|
|
|
|
":tower" -- look for a structure named "tower" in the root context.
|
|
|
|
"^tower" -- look for a structure named "tower" in the parent of the current context.
|
|
|
|
"^^towers:tower:room" -- look for a structure named "room" in "tower" in "towers" in the parent of the parent of the current context.
|
|
|
|
Context is assumed to be the live structure containing the path definitions.
|
|
|
|
Let us use this new-found knowledge to create a road between the towers of two rival wizards.
|
|
The Two Towers
|
|
|
|
This example expands on the preceding example by creating a wall-removing path between two towers.
|
|
|
|
tower {
|
|
flags CIRCLE
|
|
size_x 8~12
|
|
size_y 7~10
|
|
id_1 0
|
|
relations {
|
|
tower_walls {
|
|
flags CIRCLE|OVERLAP
|
|
}
|
|
}
|
|
}
|
|
tower_walls {
|
|
flags BORDER
|
|
size_x 100%
|
|
size_y 100%
|
|
id_1 1
|
|
}
|
|
dirt_path {
|
|
flags RECT
|
|
size_x 1
|
|
size_y 1
|
|
id_1 0
|
|
replace {
|
|
id_1 1
|
|
}
|
|
}
|
|
towers {
|
|
size_x 100%
|
|
size_y 100%
|
|
relations {
|
|
tower {
|
|
count 2
|
|
x 10~75%
|
|
y 10~75%
|
|
}
|
|
}
|
|
paths {
|
|
dirt_path {
|
|
flags DUMB|WALK
|
|
to tower
|
|
to_flags ORIGIN
|
|
from tower
|
|
from_flags ORIGIN
|
|
}
|
|
}
|
|
}
|
|
|
|
This would create a scene similar to:
|
|
|
|
...............1........................
|
|
............1111111.....................
|
|
...........110000011....................
|
|
..........11000000011...................
|
|
...........110000011.......1............
|
|
............1111100.....1111111.........
|
|
...............1..00...110000011........
|
|
...................00..100000001........
|
|
....................0011000000011.......
|
|
.....................00000000001........
|
|
.......................110000011........
|
|
........................1111111.........
|
|
...........................1............
|
|
|
|
This should give a fairly concise overview of proclib, although there are likely to be massive enhancements and changes in the future. :)
|
|
Other Examples
|
|
Little House by the Lake
|
|
|
|
................................................................
|
|
.........8.......8.........8.8.........88......8.8..............
|
|
......11111111111.........8....8........................8.......
|
|
......10000000001.........8....8................................
|
|
.....8100000000018.8........................8....8..............
|
|
......11111111111.............8.8...........8...............8...
|
|
.......................8........................................
|
|
......8.......8...........................8.....8...........8..8
|
|
............................................8...................
|
|
..8........................8......8.........................8...
|
|
...8..8....8.......8....8........8..............................
|
|
........................................8..............8........
|
|
.......8.....................8....8......................8......
|
|
..........8..8.........88........................8...8...8..8...
|
|
......8...............8..8.......8.................8.....0....8.
|
|
......88...............8.................8..........000000000000
|
|
...8.............8...............................000000000000000
|
|
..8....8...............88.......................0000000000000000
|
|
............................8.................000000000000000000
|
|
....8..................8......8.........8....0000000000000000000
|
|
........8..............8....................00000000000000000000
|
|
...................................8.......000000000000000000000
|
|
.....8..........8...8.........8............000000000000000000000
|
|
|
|
tree {
|
|
flags RECT
|
|
size_x 1
|
|
id_1 8
|
|
}
|
|
lake {
|
|
flags CIRCLE|OVERLAP
|
|
size_x 50~75%
|
|
id_1 0
|
|
}
|
|
house {
|
|
flags RECT
|
|
size_x 9~14
|
|
size_y 4~7
|
|
id_1 0
|
|
relations {
|
|
house_walls {
|
|
flags RECT
|
|
}
|
|
}
|
|
}
|
|
house_walls {
|
|
flags BORDER|OVERLAP
|
|
size_x 100%
|
|
size_y 100%
|
|
id_1 1
|
|
}
|
|
start {
|
|
size_x 64
|
|
size_y 32
|
|
relations {
|
|
lake {
|
|
count 4~6
|
|
x 50~80%
|
|
y 70~80%
|
|
}
|
|
tree {
|
|
count 64~128
|
|
x 0~100%
|
|
y 0~100%
|
|
}
|
|
house {
|
|
flags OVERLAP
|
|
count 1
|
|
x 10~50%
|
|
y 10~50%
|
|
}
|
|
}
|
|
}
|
|
|
|
Lumpy Castle
|
|
The structure definition for this one is exceptionally bad and could be refactored.
|
|
|
|
.................................................................
|
|
............................................................9....
|
|
...9.......1.........................9........1..................
|
|
........1111111............................1111111...............
|
|
.......110000011..........................1100000119.............
|
|
.......100000001..........................100000001..............
|
|
.......100000001.....................9....100000001......9.......
|
|
......1100000001111111111111111111111111111000000011.............
|
|
.......100000000000000000000000000000000000000000001.............
|
|
.......100000000000000000000000000000000000000000001.............
|
|
.......110000001111111111111111111111111111100000011....9........
|
|
........11000011...........9...............11000011..............
|
|
.........100001.............................100001...............
|
|
.........100001..............1......9.......100001...............
|
|
.........100001...........1111111...........100001...............
|
|
.........100001...9......110000011..........100001...............
|
|
.........100001..........100000001..........100001...............
|
|
.........100001........9.100000001..........100001..............9
|
|
.........100001.........11000000011.........100001...............
|
|
.........100001..........100000001..........100001...............
|
|
.........100001..........100000001..........100001...............
|
|
.9.......100001..........110000011..........100001...............
|
|
.........100001...........1111111...........100001...............
|
|
.........100001.....9........1..............100001...............
|
|
........1100001............................1100001...............
|
|
.......110000011..........................110000011..............
|
|
.......100000001..........................100000001..............
|
|
.......100000001..........................100000001....8.........
|
|
......1100000001111111111111111111111111111000000011.88888.......
|
|
.......10000000000000000000000000000000000000000001..88888.......
|
|
.9.....10000000000000000000000000000000000000000001.8888888......
|
|
.......11000001111111111111111111111111111110000011..88888.......
|
|
........1111111............................1111111...88888.......
|
|
...........1.................................81........8.........
|
|
...........................................88888.................
|
|
.............................9.............88888.............9...
|
|
..........................................8888888................
|
|
...........................................88888.................
|
|
...........................................88888.................
|
|
.............................................8...................
|
|
.................9........9.......9..............................
|
|
|
|
lake {
|
|
flags CIRCLE|ORIGIN
|
|
size_x 6~9
|
|
id_1 8
|
|
}
|
|
tree {
|
|
flags RECT|ORIGIN
|
|
size_x 1
|
|
id_1 9
|
|
replace {
|
|
id_1 9
|
|
}
|
|
}
|
|
tower_1 {
|
|
flags CIRCLE|ORIGIN
|
|
size_x 20%
|
|
id_1 0
|
|
relations {
|
|
tower_walls {
|
|
flags OVERLAP
|
|
}
|
|
}
|
|
}
|
|
tower_2 {
|
|
flags CIRCLE|ORIGIN
|
|
size_x 20%
|
|
id_1 0
|
|
relations {
|
|
tower_walls {
|
|
flags OVERLAP
|
|
}
|
|
}
|
|
}
|
|
tower_3 {
|
|
flags CIRCLE|ORIGIN
|
|
size_x 20%
|
|
id_1 0
|
|
relations {
|
|
tower_walls {
|
|
flags OVERLAP
|
|
}
|
|
}
|
|
}
|
|
tower_4 {
|
|
flags CIRCLE|ORIGIN
|
|
size_x 20%
|
|
id_1 0
|
|
relations {
|
|
tower_walls {
|
|
flags OVERLAP
|
|
}
|
|
}
|
|
}
|
|
tower_5 {
|
|
flags CIRCLE|ORIGIN
|
|
size_x 20%
|
|
id_1 0
|
|
relations {
|
|
tower_walls {
|
|
flags OVERLAP
|
|
}
|
|
}
|
|
}
|
|
tower_walls {
|
|
flags CIRCLE|BORDER
|
|
size_x 100%
|
|
size_y 100%
|
|
id_1 1
|
|
}
|
|
long_walls {
|
|
size_x 10%
|
|
size_y 10%
|
|
flags RECT|ORIGIN
|
|
id_1 0
|
|
replace {
|
|
id_1 1
|
|
}
|
|
relations {
|
|
long_walls_walls {
|
|
}
|
|
}
|
|
}
|
|
long_walls_walls {
|
|
flags RECT|BORDER|ORIGIN|OVERLAP
|
|
size_x 100%
|
|
size_y 100%
|
|
id_1 1
|
|
replace {
|
|
id_1 0
|
|
}
|
|
}
|
|
castle {
|
|
size_x 90%
|
|
size_y 90%
|
|
relations {
|
|
tower_1 {
|
|
x 20%
|
|
y 20%
|
|
}
|
|
tower_2 {
|
|
x 20%
|
|
y 80%
|
|
}
|
|
tower_3 {
|
|
x 80%
|
|
y 20%
|
|
}
|
|
tower_4 {
|
|
x 80%
|
|
y 80%
|
|
}
|
|
tower_5 {
|
|
flags ORIGIN
|
|
x 50%
|
|
y 50%
|
|
}
|
|
}
|
|
paths {
|
|
long_walls {
|
|
flags DUMB|WALK|FORCE
|
|
from tower_1
|
|
from_flags ORIGIN
|
|
to tower_2
|
|
to_flags ORIGIN
|
|
to_x -25%
|
|
}
|
|
long_walls {
|
|
flags DUMB|WALK|FORCE
|
|
from_flags ORIGIN
|
|
from_x 0%
|
|
from_y 0%
|
|
to_flags ORIGIN
|
|
to_x 0%
|
|
to_y 0%
|
|
from tower_1
|
|
to tower_3
|
|
}
|
|
long_walls {
|
|
flags DUMB|WALK|FORCE
|
|
from_flags ORIGIN
|
|
from_x 0%
|
|
from_y 0%
|
|
to_flags ORIGIN
|
|
to_x -25%
|
|
to_y 0%
|
|
from tower_3
|
|
to tower_4
|
|
}
|
|
long_walls {
|
|
flags DUMB|WALK|FORCE
|
|
from_flags ORIGIN
|
|
from_x 0%
|
|
from_y 0%
|
|
to_flags ORIGIN
|
|
to_x 0%
|
|
to_y 0%
|
|
from tower_4
|
|
to tower_2
|
|
}
|
|
}
|
|
}
|
|
start {
|
|
size_x 64~80
|
|
size_y 32~48
|
|
relations {
|
|
castle {
|
|
}
|
|
tree {
|
|
count 16~32
|
|
x 0~100%
|
|
y 0~100%
|
|
}
|
|
lake {
|
|
count 1~2
|
|
x 70~100%
|
|
y 70~100%
|
|
}
|
|
}
|
|
}
|