FloodWML
Usage
You can find sources at the bottom of the page. It's too long to include it here.
To create a flood:
{CREATE_FLOOD "1,1;2,3" "ne,n" "Gg>Ww;Gs>Wwt" awesome_flood}
Where "1,1;2,3" is a semicolon separated list of coordinate pairs where the flood starts from, "ne,n" is a comma separated list of directions in which the flood will spread, "Gg>Ww;Gs>Wwt" is a semicolon separated list of transformations where a>b means that the hexes with the terrain code a will be converted to b, and finally awesome_flood is the variable to store the current state of the flood in (but you might better think about it as the flood's id).
To spread a flood by one hex:
{SPREAD_FLOOD awesome_flood}
Where awesome_flood is the flood's id :)
To modify a flood's data:
{SET_FLOOD_DIRECTIONS "se,s" awesome_flood} {SET_FLOOD_TERRAIN_TABLE "Gg>Wwg;Gs>Ww" awesome_flood} {SET_FLOOD_SOURCE "3,3;5,4;6,6" awesome_flood}
One note: all of these macros replace current data in awesome_flood, so old information is lost. This is especially important for SET_FLOOD_SOURCE because that alters the list of hexes which are currently form the first wave of the flood. So if you call it, the original flood will stop and a new one will start from "3,3;5,4;6,6" or whatever you specify.
Source Code
#define INVERT_DIRECTIONS DIRECTIONS OUT_VAR #a macro to change directions to their opposites (n->s, sw->ne, etc) #DIRECTIONS is a comma-separated list of directions #OUT_VAR is the variable to write the output in. Output is an array #which contains the inverted directions in the order they were given #in DIRECTIONS. The values are stores in the 'direction' key. [set_variables] name={OUT_VAR} [split] list={DIRECTIONS} separator="," key=direction remove_empty=yes [/split] [/set_variables] {FOREACH {OUT_VAR} TMP_ID_i} [if] [variable] name={OUT_VAR}[$TMP_ID_i].direction equals="n" [/variable] [then] [set_variable] name={OUT_VAR}[$TMP_ID_i].direction value="s" [/set_variable] [/then] [else] [if] [variable] name={OUT_VAR}[$TMP_ID_i].direction equals="s" [/variable] [then] [set_variable] name={OUT_VAR}[$TMP_ID_i].direction value="n" [/set_variable] [/then] [else] [if] [variable] name={OUT_VAR}[$TMP_ID_i].direction equals="se" [/variable] [then] [set_variable] name={OUT_VAR}[$TMP_ID_i].direction value="nw" [/set_variable] [/then] [else] [if] [variable] name={OUT_VAR}[$TMP_ID_i].direction equals="nw" [/variable] [then] [set_variable] name={OUT_VAR}[$TMP_ID_i].direction value="se" [/set_variable] [/then] [else] [if] [variable] name={OUT_VAR}[$TMP_ID_i].direction equals="ne" [/variable] [then] [set_variable] name={OUT_VAR}[$TMP_ID_i].direction value="sw" [/set_variable] [/then] [else] [if] [variable] name={OUT_VAR}[$TMP_ID_i].direction equals="sw" [/variable] [then] [set_variable] name={OUT_VAR}[$TMP_ID_i].direction value="ne" [/set_variable] [/then] [/if] [/else] [/if] [/else] [/if] [/else] [/if] [/else] [/if] [/else] [/if] {NEXT TMP_ID_i} #enddef #define STORE_FLOODABLE_LOCATIONS SOURCE_X SOURCE_Y DIRECTIONS TERRAINS OUT_VAR #stores hexes of type TERRAINS whose neighbour in one of DIRECTIONS directions is one of SOURCE_X ; SOURCE_Y #SOURCE_X & SOURCE_Y comma-separated list of coordinates #DIRECTIONS an array of directions, values stored in the 'direction' key (same as the output format of INVERT_DIRECTIONS) #TERRAINS comma-separated list of terrain codes #OUT_VAR the variable to write the output in # #NOTE: this macro is in fact used to store the hexes of type TERRAINS which are neighbours of SOURCE_X ; SOURCE_Y in #certain directions, but we achieve that by inverting those directions outside of this macro. See INVERT_DIRECTIONS. [store_locations] variable={OUT_VAR} terrain={TERRAINS} [filter_adjacent_location] adjacent=${DIRECTIONS}[0].direction x={SOURCE_X} y={SOURCE_Y} [/filter_adjacent_location] [or] terrain={TERRAINS} [filter_adjacent_location] adjacent=${DIRECTIONS}[1].direction x={SOURCE_X} y={SOURCE_Y} [/filter_adjacent_location] [or] terrain={TERRAINS} [filter_adjacent_location] adjacent=${DIRECTIONS}[2].direction x={SOURCE_X} y={SOURCE_Y} [/filter_adjacent_location] [or] terrain={TERRAINS} [filter_adjacent_location] adjacent=${DIRECTIONS}[3].direction x={SOURCE_X} y={SOURCE_Y} [/filter_adjacent_location] [or] terrain={TERRAINS} [filter_adjacent_location] adjacent=${DIRECTIONS}[4].direction x={SOURCE_X} y={SOURCE_Y} [/filter_adjacent_location] [or] terrain={TERRAINS} [filter_adjacent_location] adjacent=${DIRECTIONS}[5].direction x={SOURCE_X} y={SOURCE_Y} [/filter_adjacent_location] [/or] [/or] [/or] [/or] [/or] [/store_locations] #enddef #define SPLIT_PAIRS PAIRS SEP1 SEP2 OUT_VAR [set_variables] name=TMP_pairs [split] list={PAIRS} key=pair separator={SEP1} remove_empty=true [/split] [/set_variables] {FOREACH TMP_pairs TMP_SP_i} [set_variables] name=TMP_splitted [split] list=$TMP_pairs[$TMP_SP_i].pair separator={SEP2} key=value [/split] [/set_variables] [set_variable] name={OUT_VAR}[$TMP_SP_i].value1 value=$TMP_splitted[0].value [/set_variable] [set_variable] name={OUT_VAR}[$TMP_SP_i].value2 value=$TMP_splitted[1].value [/set_variable] {NEXT TMP_SP_i} {CLEAR_VARIABLE TMP_pairs} {CLEAR_VARIABLE TMP_splitted} #enddef #define FLOOD_SINGLE_HEX X Y TERRAIN_TABLE [store_locations] variable=TMP_current_hex x={X} y={Y} [/store_locations] {FOREACH {TERRAIN_TABLE} FSH_i} [if] [variable] name=TMP_current_hex.terrain equals=${TERRAIN_TABLE}[$FSH_i].value1 [/variable] [then] {MODIFY_TERRAIN ${TERRAIN_TABLE}[$FSH_i].value2 {X} {Y}} [set_variable] name=FSH_i value=${TERRAIN_TABLE}.length [/set_variable] [/then] [/if] {NEXT FSH_i} {CLEAR_VARIABLE TMP_current_hex} #enddef #define SET_FLOOD_TERRAIN_TABLE TERRAIN_TABLE DATA_VAR {SPLIT_PAIRS {TERRAIN_TABLE} ";" ">" {DATA_VAR}.terrain_table} [set_variable] name={DATA_VAR}.floodable_terrains [join] variable={DATA_VAR}.terrain_table separator="," key=value1 [/join] [/set_variable] #enddef #define SET_FLOOD_DIRECTIONS DIRECTIONS DATA_VAR {INVERT_DIRECTIONS {DIRECTIONS} {DATA_VAR}.directions} #enddef #define SET_FLOOD_SOURCE SOURCE DATA_VAR {SPLIT_PAIRS {SOURCE} ";" "," TMP_source_coordinates} [set_variable] name={DATA_VAR}.fields_x [join] variable=TMP_source_coordinates key=value1 separator="," [/join] [/set_variable] [set_variable] name={DATA_VAR}.fields_y [join] variable=TMP_source_coordinates key=value2 separator="," [/join] [/set_variable] #enddef #define CREATE_FLOOD SOURCE DIRECTIONS TERRAIN_TABLE DATA_VAR [clear_variable] name={DATA_VAR} [/clear_variable] {SET_FLOOD_SOURCE {SOURCE} {DATA_VAR}} {SET_FLOOD_TERRAIN_TABLE {TERRAIN_TABLE} {DATA_VAR}} {SET_FLOOD_DIRECTIONS {DIRECTIONS} {DATA_VAR}} #enddef #define SPREAD_FLOOD DATA_VAR {STORE_FLOODABLE_LOCATIONS ${DATA_VAR}.fields_x ${DATA_VAR}.fields_y {DATA_VAR}.directions ${DATA_VAR}.floodable_terrains TMP_floodable} {FOREACH TMP_floodable TMP_SF_i} {FLOOD_SINGLE_HEX $TMP_floodable[$TMP_SF_i].x $TMP_floodable[$TMP_SF_i].y {DATA_VAR}.terrain_table} {NEXT TMP_SF_i} [redraw][/redraw] [set_variable] name={DATA_VAR}.fields_x [join] variable=TMP_floodable key=x separator="," [/join] [/set_variable] [set_variable] name={DATA_VAR}.fields_y [join] variable=TMP_floodable key=y separator="," [/join] [/set_variable] #enddef #undef SPLIT_PAIRS #undef INVERT_DIRECTIONS #undef STORE_FLOODABLE_LOCATIONS #undef FLOOD_SINGLE_HEX