# This file contains general utility macros for WML authors.
#
# Later macros in this file are built using earlier ones, which
# is why they live hear rather than being broken out into topic-specific files.

# ! in comments is used in generating HTML documentation, ignore it otherwise.

#### TABLE OF CONTENTS ####

# variable operations

#   RANDOM
#   VARIABLE
#   VARIABLE_OP
#   CLEAR_VARIABLE
#   FOREACH
#   NEXT
#   IF_TERRAIN
#   DEBUG_MSG

# scenario/campaign setup

#   STARTING_VILLAGES
#   MENU_IMG_TXT
#   MENU_IMG_TXT2

# side setup

#   TURNS
#   GOLD
#   INCOME
#   ATTACK_DEPTH
#   NO_SCOUTS

# in-scenario actions

#   UNIT
#   UNDEAD_UNIT
#   CREATE_UNIT
#   MOVE_UNIT
#   MODIFY_UNIT
#   STORE_UNIT_VAR
#   PUT_TO_RECALL_LIST

# utilities not intended for general use

#   QUANTITY

#### END OF TABLE OF CONTENTS ####

#define QUANTITY ATTRIBUTE ON_EASY ON_NORMAL ON_HARD
# Macro to define a 'quantity' differently based on difficulty levels.
#ifdef EASY
{ATTRIBUTE}={ON_EASY}
#endif
#ifdef NORMAL
{ATTRIBUTE}={ON_NORMAL}
#endif
#ifdef HARD
{ATTRIBUTE}={ON_HARD}
#endif
#enddef

#define TURNS ON_EASY ON_NORMAL ON_HARD
# Macro to define number of turns for different difficulty levels.
{QUANTITY turns {ON_EASY} {ON_NORMAL} {ON_HARD}}
#enddef


#define GOLD ON_EASY ON_NORMAL ON_HARD
# Macro which will let you say {GOLD x y z} to set
# starting gold depending on easy/medium/hard - x/y/z
{QUANTITY gold {ON_EASY} {ON_NORMAL} {ON_HARD}}
#enddef

#define INCOME ON_EASY ON_NORMAL ON_HARD
# Macro which will let you say {GOLD x y z} to set
# per-turn income depending on easy/medium/hard - x/y/z
{QUANTITY income {ON_EASY} {ON_NORMAL} {ON_HARD}}
#enddef

#define ATTACK_DEPTH ON_EASY ON_NORMAL ON_HARD
# Macro to define AI attack depth for different difficulty levels
# (set it to 1-6)
{QUANTITY attack_depth {ON_EASY} {ON_NORMAL} {ON_HARD}}
#enddef

#define NO_SCOUTS
# Macro to make an AI team not recruit scouts.
villages_per_scout=0
#enddef

#define RANDOM RANGE
# Macro to quickly pick a random value (in the $random variable, to avoid
# cluttering up savegames with such temporary variables).
[set_variable]
name=random
random={RANGE}
[/set_variable]
#enddef

#define VARIABLE VAR VALUE
# Macro to initialize a variable.  Strictly a syntatic shortcut.
[set_variable]
name={VAR}
value={VALUE}
[/set_variable]
#enddef

#define VARIABLE_OP VAR OP ARG
# Macro to do mathematical operations on variables.
[set_variable]
name={VAR}
{OP}={ARG}
[/set_variable]
#enddef

#define CLEAR_VARIABLE VAR
# Macro to clear a variable previously set.
[clear_variable]
name={VAR}
[/clear_variable]
#enddef

#define FOREACH ARRAY VAR
# Macro to begin a WML clause that iterates over an array.
{VARIABLE {VAR} 0}
[while]
    [variable]
    name={VAR}
    less_than=${ARRAY}.length
    [/variable]
    [do]
#enddef

#define NEXT VAR
# Macro to end a WML clause that iterates over an array.
    [set_variable]
    name={VAR}
    add=1
    [/set_variable]
    [/do]
[/while]
{CLEAR_VARIABLE {VAR}}
#enddef

#define DEBUG_MSG MSG
# Emit a debug message.  Meant to be overridden with no-op definition
# of the same name for proction use.
[message]
speaker=narrator
message={MSG}
[/message]
#enddef

#define MODIFY_UNIT FILTER VAR VALUE
# Alters a unit variable (such as unit.x, unit.type,
# unit.side), handling all the storing and unstoring.
#
# Example that flips all spearmen to side 2:
#! {MODIFY_UNIT type=Spearman side 2}
    [store_unit]
        [filter]
            {FILTER}
        [/filter]

        variable=MODIFY_UNIT_store
        kill=yes
    [/store_unit]

    {FOREACH MODIFY_UNIT_store MODIFY_UNIT_i}
        [set_variable]
            name=MODIFY_UNIT_store[$MODIFY_UNIT_i].{VAR}
            value={VALUE}
        [/set_variable]

        [unstore_unit]
            variable=MODIFY_UNIT_store[$MODIFY_UNIT_i]
            find_vacant=no
        [/unstore_unit]
    {NEXT MODIFY_UNIT_i}

    {CLEAR_VARIABLE MODIFY_UNIT_store}
#enddef

#define STORE_UNIT_VAR FILTER VAR TO_VAR
# Stores an attribute of a unit to the given variable.
#
# Example where this is used to flip all orcs to whatever side James is on:
#! {STORE_UNIT_VAR description=James side side_of_James}
#! {MODIFY_UNIT race=orc side $side_of_James}
    [store_unit]
        [filter]
            {FILTER}
        [/filter]

        kill=no
        variable=STORE_UNIT_VAR_store
    [/store_unit]

    {VARIABLE_OP {TO_VAR} format $STORE_UNIT_VAR_store.{VAR}}

    {CLEAR_VARIABLE STORE_UNIT_VAR_store}
#enddef

#define IF_TERRAIN X Y TYPES CONTENTS
# This is a way to check whether or not the terrain in the given coordinates
# is of the given type or types. Might be useful, since filtering by terrain
# isn't possible directly.
#
# You can use it, for example, like this:
#! [event]
#!     name=moveto
#!     first_time_only=no
#!
#!     {IF_TERRAIN $x1 $y1 gfm (
#!         [then]
#!             {DEBUG_MSG "Stepped on grassland, forest or mountains!"}
#!         [/then]
#!     )}
#! [/event]
    [store_locations]
        x={X}
        y={Y}
        terrain={TYPES}
        variable=IF_TERRAIN_temp
    [/store_locations]

    [if]
        [variable]
            name=IF_TERRAIN_temp.length
            not_equals=0
        [/variable]

        {CONTENTS}
    [/if]

    {CLEAR_VARIABLE IF_TERRAIN_temp}
#enddef

#define CREATE_UNIT SIDE TYPE X Y UNIT_ID OTHER
# Creates a unit of TYPE belonging to SIDE at X,Y. UNIT_ID can be used
# when filtering on it.  For example, let's create a wose for player 1
# at 4,7
#
#! {CREATE_UNIT 1 "Wose" 4 7 () ()}
#
# As a second example, let's make it a female wose which can recruit and
# is name "Woselina":
#
#! {CREATE_UNIT 1 "Wose" 4 7 "Woselina" (
# 	canrecruit=1
# )}
	[unit]
		side={SIDE}
		type={TYPE}
		x={X}
		y={Y}
		description={UNIT_ID}
		user_description=" "

		upkeep=full
		animate=yes
		{OTHER}
	[/unit]
#enddef

#define MOVE_UNIT FILTER TO_X TO_Y
# Moves a unit from its current location to the given location along a
# relatively straight line displaying the movement just like [move_unit_fake]
# does.
#
# Note that setting the destination on an existing unit does not kill either
# one, but causes the unit to move to the nearest vacant hex instead.
    [store_unit]
        [filter]
            {FILTER}
        [/filter]

        variable=MOVE_UNIT_temp
        kill=no
    [/store_unit]

    [scroll_to]
        x=$MOVE_UNIT_temp.x
        y=$MOVE_UNIT_temp.y
    [/scroll_to]

    {VARIABLE_OP MOVE_UNIT_path_coords_x format ("$MOVE_UNIT_temp.x|,{TO_X}")}
    {VARIABLE_OP MOVE_UNIT_path_coords_y format ("$MOVE_UNIT_temp.y|,{TO_Y}")}

    {VARIABLE MOVE_UNIT_temp.x {TO_X}}
    {VARIABLE MOVE_UNIT_temp.y {TO_Y}}

    [kill]
    	{FILTER}

    	animate=no
    	fire_event=no
    [/kill]

    [move_unit_fake]
        type=$MOVE_UNIT_temp.type
        side=$MOVE_UNIT_temp.side
        x=$MOVE_UNIT_path_coords_x
        y=$MOVE_UNIT_path_coords_y
    [/move_unit_fake]

    [unstore_unit]
    	variable=MOVE_UNIT_temp
    	find_vacant=yes
    [/unstore_unit]

    [redraw][/redraw]

    {CLEAR_VARIABLE MOVE_UNIT_temp}
    {CLEAR_VARIABLE MOVE_UNIT_path_coords_x}
    {CLEAR_VARIABLE MOVE_UNIT_path_coords_y}
#enddef

#define PUT_TO_RECALL_LIST FILTER
# This places a given unit back to the recall list of the side it is on.
# Note however, that the unit is not healed to full health, so when
# recalled (even if not until the next scenario) the unit may have less
# than his maximum hp left.
#
# An example that returns all units stepping on (20,38) back to the recall
# list:
#
#! [event]
#!     name=moveto
#!
#!     [filter]
#!         x,y=20,38
#!     [/filter]
#!
#!     {PUT_TO_RECALL_LIST x,y=20,38}
#! [/event]
    [store_unit]
        [filter]
            {FILTER}
        [/filter]

        variable=PUT_TO_RECALL_LIST_temp
        kill=yes
    [/store_unit]

    {FOREACH PUT_TO_RECALL_LIST_temp i}
        {VARIABLE PUT_TO_RECALL_LIST_temp[$i].x "recall"}
        {VARIABLE PUT_TO_RECALL_LIST_temp[$i].y "recall"}

        [unstore_unit]
            variable=PUT_TO_RECALL_LIST_temp[$i]
            find_vacant=no
        [/unstore_unit]
    {NEXT i}
#enddef

#define STARTING_VILLAGES SIDE RADIUS
# Macro to make a side start a scenario with villages
[event]
name=prestart
    [store_starting_location]
    side={SIDE}
    variable=temp_starting_location
    [/store_starting_location]
    [store_locations]
    x,y=$temp_starting_location.x,$temp_starting_location.y
    radius={RADIUS}
    #all the types of villages
	[and]
	    terrain=Ha^Vhha, Hh^Vhh, Dd^Vda, Mm^Vhh, Uu^Vu, Aa^Vea, Gs^Vht, Uu^Vud, Gg^Ve, Dd^Vdt, Gg^Vh, Aa^Vha, Ww^Vm, Ss^Vhs, Ss^Vm
	[/and]
    variable=temp_starting_locs
    [/store_locations]

    {FOREACH temp_starting_locs i}
        {VARIABLE_OP temp_x_var to_variable temp_starting_locs[$i].x}
        {VARIABLE_OP temp_y_var to_variable temp_starting_locs[$i].y}
        [capture_village]
        side={SIDE}
        x,y=$temp_x_var,$temp_y_var
        [/capture_village]
    {NEXT i}

    {CLEAR_VARIABLE temp_x_var}
    {CLEAR_VARIABLE temp_y_var}
    {CLEAR_VARIABLE temp_starting_location}
    {CLEAR_VARIABLE temp_starting_locs}
    {CLEAR_VARIABLE i}
[/event]
#enddef

#define UNIT TYPE DESCRIPTION UDESCRIPTION SIDE X Y
# Create a unit with the Loyal trait.
#
# Example:
#! {UNIT (Elvish Fighter) (Myname) ( _ "Myname") 1 1 1}
#
    [unit]
        type={TYPE}
        description={DESCRIPTION}
        user_description={UDESCRIPTION}
        side={SIDE}
        x={X}
        y={Y}
        [modifications]
            {TRAIT_LOYAL}
        [/modifications]
    [/unit]
#enddef

#define UNDEAD_UNIT TYPE SIDE X Y
# Create a unit with the Undead and Loyal traits.
    [unit]
        type={TYPE}
        side={SIDE}
        x={X}
        y={Y}
        [modifications]
            {TRAIT_UNDEAD}
            {TRAIT_LOYAL}
        [/modifications]
    [/unit]
#enddef

# FIXME: Documentation for these is needed.

#define MENU_IMG_TXT IMG TXT
"&"+{IMG}+"="+{TXT}#enddef

#define MENU_IMG_TXT2 IMG TXT1 TXT2
"&"+{IMG}+"="+{TXT1}+"="+{TXT2}#enddef


