Scrap the random guard placement

The guard placement randomization is practically impossible to write so
that it'd guarantee a route through the map without making it too
trivial.

Now, there are 3 separate hardcoded guard layouts, one of which will be
chosen at random.
This commit is contained in:
ln-zookeeper 2014-12-09 16:20:01 +02:00
parent 73a8176833
commit 5a2e76e79e
3 changed files with 101 additions and 233 deletions

View file

@ -4,7 +4,9 @@ Version 1.12.0+dev:
not set
* Lurkers MAI: bug fix for attack error when lurker runs into ambush
* Stationed Guardian Micro AI: bug fix for unreachable stations
* Campaigns
* Campaigns:
* Liberty:
* Fixed possibility of no viable routes around guards in 'Hide and Seek'.
* Son of the Black Eye:
* S6 Black Flag: reduce randomness of unit types unloading from galleons
* Editor:

View file

@ -155,250 +155,113 @@
[/unit]
#enddef
{SEEKER 3 42 (Iron Mauler)}
{SEEKER 15 37 (Shock Trooper)}
{SEEKER 17 38 (Shock Trooper)}
{SEEKER 2 45 (Bowman)}
{SEEKER 3 47 (Bowman)}
# Here we approximate the vision area extending around all units and
# initialize the loop variables, both of which we need when randomly
# placing the guards below
{RANDOM "a,b,c"}
[switch]
variable=random
[store_locations]
[filter]
[/filter]
radius=6
[filter_radius]
terrain=Gg,R*,Re^Gvs,*^V*,C*
[/filter_radius]
variable=total_vision_area
[/store_locations]
{VARIABLE guards 1}
{VARIABLE loops 0}
# This loop which places most of the guards works like this:
#
# - generate a new guard (at 1,1, no real location for it yet)
# - figure out the vision range of this unit (dependant on unit type and
# traits) and a few other helper variables
# - store all the locations on which the vision range of the new guard
# wouldn't touch the vision range of any other unit.
# - pick one of those locations randomly, and place the new guard there.
# - pick a random location which satisfies the same condition (but
# ignoring the vision range of the new guard) around the new guard,
# and place an assistant guard there, so guards are almost always
# paired.
# - update the total vision range with those of the new guards.
# - repeat until 20 guards are placed or we've repeated 25 times.
#
# Note that when calculating vision ranges of units, the vision range is
# only approximated, by only allowing the simulated vision range to
# penetrate terrain=Gg,R*,Re^Gvs,*^V*,C*. However, this is a good enough
# estimate when the map doesn't contain thin walls of other terrains.
#
# The result is the map filled with randomly placed pairs of guards,
# which all have a hex or two of space between their vision ranges, thus
# allowing the player to sneak through the map without being spotted.
# It might not be perfect, but it seems to work perfectly most of the
# time.
[while]
[variable]
name=guards
less_than=20
[/variable]
[variable]
name=loops
less_than=25
[/variable]
[do]
{VARIABLE_OP guard_type rand "Shock Trooper"}
[unit]
x,y=1,1
side=2
type=$guard_type
random_traits=yes
generate_name=yes
[/unit]
[store_unit]
[filter]
x,y=1,1
[/filter]
kill=yes
variable=stored_guard
[/store_unit]
[if]
[variable]
name=stored_guard.modifications.trait[0].id
not_equals=quick
[/variable]
[variable]
name=stored_guard.modifications.trait[1].id
not_equals=quick
[/variable]
[then]
{VARIABLE guard_MP $stored_guard.max_moves}
[/then]
[else]
{VARIABLE guard_MP $stored_guard.max_moves}
{VARIABLE_OP guard_MP add 1}
[/else]
[/if]
{VARIABLE guard_vision_range $guard_MP}
{VARIABLE_OP guard_vision_range add 1}
{VARIABLE guard_vision_range_plus_1 $guard_vision_range}
{VARIABLE_OP guard_vision_range_plus_1 add 1}
{VARIABLE guard_vision_range_plus_3 $guard_vision_range}
{VARIABLE_OP guard_vision_range_plus_3 add 3}
[case]
value=a
[store_locations]
[and]
find_in=total_vision_area
radius=$guard_vision_range_plus_3
[filter_radius]
terrain=Gg,R*,Re^Gvs,*^V*,C*
[/filter_radius]
[/and]
[not]
find_in=total_vision_area
radius=$guard_vision_range_plus_1
[filter_radius]
terrain=Gg,R*,Re^Gvs,*^V*,C*
[/filter_radius]
[/not]
[and]
terrain=Gg,R*,Re^Gvs,*^V*,C*
[/and]
variable=new_guard_locations
x= 7,19,24,30,17,25, 2, 6,18, 2,24,13,16, 3,15,17,30,19, 3,27, 9
y=13, 9,10,13,18,21,22,23,27,28,30,32,32,37,37,38,38,41,42,43,47
variable=guard_locs
[/store_locations]
[/case]
[case]
value=b
[store_locations]
x= 2,25,14,30, 5,16,25, 6, 2,33,16,22,13, 3,15,17,28, 3, 7,21
y=10,10,13,13,19,20,21,23,28,28,31,31,32,37,37,38,39,42,48,48
variable=guard_locs
[/store_locations]
[/case]
[case]
value=c
[store_locations]
x=22, 7,16,26,15, 4,31,19,15,30, 5, 4, 8,15,17,27,19, 3,20
y=12,13,13,15,18,22,23,26,27,29,32,35,35,37,38,39,41,42,46
variable=guard_locs
[/store_locations]
[/case]
[/switch]
{FOREACH guard_locs i}
# The guard positions are designed to work with 4MP guards only, so
# we need to make sure the guards cannot get the quick trait, and we
# do this by randomizing their traits manually.
[set_variables]
name=traits_without_quick
[value]
{TRAIT_STRONG}
[/value]
[value]
{TRAIT_RESILIENT}
[/value]
[value]
{TRAIT_FEARLESS}
[/value]
[value]
{TRAIT_INTELLIGENT}
[/value]
[/set_variables]
{VARIABLE_OP first_trait rand "0..3"}
[set_variables]
name=this_guard_traits
to_variable=traits_without_quick[$first_trait].trait
[/set_variables]
# To prevent the same trait from being picked twice, we need to find
# and remove the first picked trait from the array.
{FOREACH traits_without_quick j}
[if]
[variable]
name=traits_without_quick[$j].trait.id
equals=$traits_without_quick[$first_trait].trait.id
[/variable]
{IF_VAR new_guard_locations.length greater_than 0 (
[then]
{VARIABLE_OP random_i rand "1..$new_guard_locations.length"}
{VARIABLE_OP random_i sub 1}
{VARIABLE stored_guard.x $new_guard_locations[$random_i].x}
{VARIABLE stored_guard.y $new_guard_locations[$random_i].y}
[unstore_unit]
variable=stored_guard
[/unstore_unit]
[store_locations]
[and]
x,y=$stored_guard.x,$stored_guard.y
radius=2
[/and]
[not]
find_in=total_vision_area
radius=7
[filter_radius]
terrain=Gg,R*,Re^Gvs,*^V*,C*
[/filter_radius]
[/not]
[not]
terrain=*^F*,Hh,Ww,Wo,Ss,Ds
[/not]
variable=new_assistant_guard_locations
[/store_locations]
{IF_VAR new_assistant_guard_locations.length greater_than 0 (
[then]
{VARIABLE_OP random_i rand "1..$new_assistant_guard_locations.length"}
{VARIABLE_OP random_i sub 1}
{VARIABLE_OP assistant_guard_type rand "Shock Trooper,Shock Trooper,Iron Mauler,Javelineer,Swordsman,Pikeman"}
[unit]
type=$assistant_guard_type
side=2
x,y=$new_assistant_guard_locations[$random_i].x,$new_assistant_guard_locations[$random_i].y
generate_name=yes
random_traits=yes
[/unit]
[store_locations]
[and]
x,y=$new_assistant_guard_locations[$random_i].x,$new_assistant_guard_locations[$random_i].y
radius=6
[filter_radius]
terrain=Gg,R*,Re^Gvs,*^V*,C*
[/filter_radius]
[/and]
[or]
find_in=total_vision_area
[/or]
variable=total_vision_area
[/store_locations]
[/then]
)}
[store_locations]
[and]
x,y=$stored_guard.x,$stored_guard.y
radius=$guard_vision_range
[filter_radius]
terrain=Gg,R*,Re^Gvs,*^V*,C*
[/filter_radius]
[/and]
[or]
find_in=total_vision_area
[/or]
variable=total_vision_area
[/store_locations]
{VARIABLE_OP guards add 1}
{CLEAR_VARIABLE traits_without_quick[$first_trait]}
[/then]
)}
[/if]
{NEXT j}
{VARIABLE_OP loops add 1}
[/do]
[/while]
{VARIABLE_OP second_trait rand "0..2"}
[set_variables]
name=this_guard_traits
mode=append
to_variable=traits_without_quick[$second_trait].trait
[/set_variables]
{CLEAR_VARIABLE total_vision_area}
{CLEAR_VARIABLE new_guard_locations}
{CLEAR_VARIABLE new_assistant_guard_locations}
{CLEAR_VARIABLE guard_type}
{CLEAR_VARIABLE assistant_guard_type}
{CLEAR_VARIABLE stored_guard}
{CLEAR_VARIABLE guard_MP}
{CLEAR_VARIABLE guard_vision_range}
{CLEAR_VARIABLE guard_vision_range_plus_1}
{CLEAR_VARIABLE guard_vision_range_plus_3}
{CLEAR_VARIABLE guards}
{CLEAR_VARIABLE loops}
{RANDOM "Shock Trooper,Iron Mauler"}
[unit]
type=$random
side=2
x,y=$guard_locs[$i].x,$guard_locs[$i].y
generate_name=yes
random_traits=no
[modifications]
[insert_tag]
name=trait
variable=this_guard_traits
[/insert_tag]
[/modifications]
[/unit]
{CLEAR_VARIABLE this_guard_traits}
{NEXT i}
{CLEAR_VARIABLE guard_locs,traits_without_quick,first_trait,second_trait,random}
[store_unit]
[filter]

View file

@ -3,6 +3,9 @@ changes may be omitted). For a complete list of changes, see the main
changelog: https://github.com/wesnoth/wesnoth/blob/1.12/changelog
Version 1.12.0+dev:
* Campaigns:
* Liberty:
* Fixed possibility of no viable routes around guards in 'Hide and Seek'.
* Language and i18n:
* Updated translations: Portuguese.