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:
parent
73a8176833
commit
5a2e76e79e
3 changed files with 101 additions and 233 deletions
|
@ -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:
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue