Author Topic: Mapscript Questions  (Read 16921 times)

Offline Hobbes

  • Commander
  • *****
  • Posts: 2101
  • Infiltration subroutine in progress
    • View Profile
Re: Mapscript Questions
« Reply #15 on: December 08, 2014, 04:40:42 pm »
Falko,

Do you think this would be useful to explain the coordinates on the rects?

Offline Falko

  • Commander
  • *****
  • Posts: 802
    • View Profile
Re: Mapscript Questions
« Reply #16 on: December 10, 2014, 06:52:33 pm »
looks good/helpfull@Hobbes

with the newest nightly (thx warboy) it is possible to make a random map resize depending on existing mapsize
this is what i want to explain for now
i underline the words i explain a bit more in the text so the reader can find these parts easier
it also is useful as an explanation how label, conditionals and executionChances work
i use the FARM terrain here so the rul file alone should be enough to test things
i will now explain my approach in testing mapscript and go from smaller steps to the full script at the end there is the full code if you dont want to read this stuff
i just make a new ufo-battle with farm as terrain the principle is usable for all maps
ok whats label?
https://www.ufopaedia.org/index.php?title=Ruleset_Reference_Nightly_%28OpenXcom%29#Map_Scripts says
Quote
A numeric label that can be used for conditional execution of commands. Each label should be unique within the command list (0=default no need for uniqueness).
so any command can have a label - if the command is executed successfully (at least once) this label gets a "true" value
not yet executed or failed labels have a "false" value
so here we add a 10x10 mapblock at the position 4,4 and give the command 1005 as label
Code: [Select]
      - type: addBlock
        label: 1005
        size: 1
        rects:
          - [4, 4, 1, 1]
since counting starts with 0 a block can only be placed at 4,4 if the map is at least 5x5
farm maps come in 4x4 and 5x5 version depending on ufo size
here i made a simple test for mapsize
it adds the 4,4 block; the craft and the ufo
after that we use conditionals
Code: [Select]
      - type: fillArea
        conditionals: [1005]
..
      - type: fillArea
        conditionals: [-1005]
only one of these commands will be executed
one of them (placement failed = negative labelnumber) fills the map normally
the other (placement succeded = positive labelnumber) fills the map with just one blocktype
Code: [Select]
  - type: FARM
    commands:
      #try to add a block at 4,4 position (label 1005) = test for 5x5 map
      - type: addBlock
        label: 1005
        size: 1
        rects:
          - [4, 4, 1, 1]
      - type: addUFO
      - type: addCraft
      #test: if conditionals fit make it a 1 blocktype only map (for visual conditional tests)
      - type: fillArea
        blocks: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]
        maxUses: [300, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
        freqs: [300, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
        conditionals: [1005]
      - type: fillArea
        blocks: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]
        maxUses: [3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3]
        conditionals: [-1005]

testing this you will see all medium/small scouts are in normal terrain and all bigger ufos are in a one-type-block terrain (ufo, craft and the 4,4 corner are different)
now we know 1005=true means its a 5x5 map (assuming thats the miximum size for FARM terrain)
i admit i do not know if modder can add ufos bigger than STR_BATTLESHIP and if the starting mapsize grows with it (if yes one need to accomodate for this)

so now we cant just do
addblock ...
if 1005==true: resize..
because resizing with a (partially) filled map is not allowed
so we delete the 4,4-"testblock" (FYI there was a small error in the code that was fixed in the latest nightly)

Code: [Select]
      - type: addBlock
        label: 1005
        size: 1
        rects:
          - [4, 4, 1, 1]
      #if sucess (1005) delete block
      - type: removeBlock
        rects:
          - [4, 4, 1, 1]
        conditionals: [1005]

now we have a empty map and can do the resizing
i keep it simple
4x4 map should have 33% chance to grow to 6x6
4x4 map should have 33% chance to grow to 5x5
4x4 map should have 33% chance to stay the same size
5x5 map should have 33% chance to grow to 7x7
5x5 map should have 33% chance to grow to 6x6
5x5 map should have 33% chance to stay the same size

short explanation to the resize command
in most cases you just reset the x/y values but you can also  resize the height (size: [6,6,8])
we give the execution a propability of 33% (executionChances: 33) to resize the map to 7x7 if its a 5x5 map (1005==true)
also saving the result of that chance-execution into the label 1507 is important (the label 1507 is arbitrary hint: - 5x5 map resized to 7x7)
Code: [Select]
      #if 5x5 map 33% to make it 7x7 map
      - type: resize
        label: 1507
        size: [7,7]
        executionChances: 33
        conditionals: [1005]

in the next step we use 2 conditionals we want to resize the map to 6x6 ONLY if it starts at 5x5 (1005==true) and the 7x7 resize failed (1507==false)
so we put two number in the conditionals: [1005, -1507]
but why using executionChances: 50 insted of the 33% we declared above?
the commands are executed one after another so if you create 100 maps the first command will (on average) convert 33 of them into 7x7 maps
if i convert the remaining 67 maps with e 33% executionchance i get 33,22,45
with 50% chance i get 33,33,34 distribution
Code: [Select]
      #if 5x5 map 33%=(100-33)*0.5 to make it 6x6 map else it is not resized
      - type: resize
        label: 1506
        size: [6,6]
        executionChances: 50
        conditionals: [1005, -1507]

i do not need a command for "not resizing" if 1507 and 1506 failed
in the next steps i just repeat the same steps for the 4x4 maps but with the assumption of 4x4 (1005==false)

the full script:

Code: [Select]
  - type: FARM
    commands:
      #try to add a block at 4,4 position (label 1005) = test for 5x5 map
      - type: addBlock
        label: 1005
        size: 1
        rects:
          - [4, 4, 1, 1]
      #if sucess (1005) delete block
      - type: removeBlock
        rects:
          - [4, 4, 1, 1]
        conditionals: [1005]
      #if 5x5 map 33% to make it 7x7 map
      - type: resize
        label: 1507
        size: [7,7]
        executionChances: 33
        conditionals: [1005]
      #if 5x5 map 33%=(100-33)*0.5 to make it 6x6 map else it is not resized
      - type: resize
        label: 1506
        size: [6,6]
        executionChances: 50
        conditionals: [1005, -1507]
      #if NOT 5x5 map (=4x4) 33% to make it 6x6 map
      - type: resize
        label: 1407
        size: [6,6]
        executionChances: 33
        conditionals: [-1005]
      #if NOT 5x5 map (=4x4) 33%=(100-33)*0.5 to make it 5x5 map else it is not resized
      - type: resize
        label: 1406
        size: [5,5]
        executionChances: 50
        conditionals: [-1005, -1407]

      - type: addUFO
      - type: addCraft
      #test: if conditionals fit make it a 1 blocktype only map (for visual conditional tests)
      #- type: fillArea
        #blocks: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]
        #maxUses: [300, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
        #freqs: [300, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
        #conditionals: [1005]
      - type: fillArea
        blocks: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]
        maxUses: [3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3]
        #conditionals: [-1005]

another approach:
Spoiler:
while writing this i thought about another approach to this
a map should have 33% chance to grow to 6x6
a map should have 33% chance to grow to 5x5
4x4 map should have 33% chance to stay the same size
5x5 map should have 33% chance to grow to 7x7
this approach is shorter but also shows you need to test things for yourself
while this script worked fine for 4x4 map i could not get it to work for 5x5 i got ~10 times a 7x7 map with a starting 5x5 map

Code: [Select]
  - type: FARM
    commands:
      #try to add a block at 4,4 position (label 1005) = test for 5x5 map
      - type: addBlock
        label: 1005
        size: 1
        rects:
          - [4, 4, 1, 1]
      #if sucess (1005) delete block
      - type: removeBlock
        rects:
          - [4, 4, 1, 1]
        conditionals: [1005]
      #33% chance for 5x5
      - type: resize
        label: 2005
        size: [5,5]
        executionChances: 33       
      #if 5x5 resized try 6x6 map 33%=(100-33)*0.5
      - type: resize
        label: 2006
        size: [6,6]
        conditionals: [-2005]
        executionChances: 50
      #if its a 5x5 map (1005) and the 5/6 resize failed make it a 7x7 map else no resize (=4x4 map)
      - type: resize
        label: 2007
        size: [7,7]
        conditionals: [-2005, -2006, 1005]
i have some ideas why that is but it would need further testing

Offline robin

  • Commander
  • *****
  • Posts: 1213
  • ULTIMATE ROOKIE
    • View Profile
Re: Mapscript Questions
« Reply #17 on: December 25, 2014, 01:29:33 pm »
This is my script for the Temple of Sirius maps:

mapScripts:
  - type: TEMPLE
    commands:
    - type: addBlock
      groups: 2
    - type: addBlock
      #..and so on..#

It seems though that that first command, adding the mapblock where xcom agents spawn, sometimes fails/doesn't get executed.
(I then get the error "Can't place xcom unit on map"-or-something, and the game closes up).

this is the mapblock in question:

      - name: CBASE_05
        width: 10
        length: 20
        groups: 2
        revealedFloors: 1


Why it fails, and how can I make  it "not fail ever", since that mapblock is needed?


Offline Falko

  • Commander
  • *****
  • Posts: 802
    • View Profile
Re: Mapscript Questions
« Reply #18 on: December 25, 2014, 03:48:51 pm »
without the map failes or even the full script my geuss would be that this first command does not work
do this
make two different 10x10 blocks with group 3 and 4
use this script 
Code: [Select]
    - type: addBlock
      groups: 2
      label: 1005
      #- type: addUFO
      #- type: addCraft
      #test: if conditionals fit make it a 1 blocktype only map (for visual conditional tests)
      - type: fillArea
        groups: 3
        conditionals: [1005]
      - type: fillArea
        groups: 4
        conditionals: [-1005]
in theory it should alway give a map filled with group3 blocks + one group 2 block
if that always crashes the first command is never executed
next try would be to define the blocksize because width != length
Code: [Select]
    - type: addBlock
      groups: 2
      size: [1, 2] #or [2,1] ?

Offline robin

  • Commander
  • *****
  • Posts: 1213
  • ULTIMATE ROOKIE
    • View Profile
Re: Mapscript Questions
« Reply #19 on: December 25, 2014, 04:21:24 pm »
Sometimes it works, sometimes it doesn't. I just want it to work all the time.
I'll try with the "size" thing.

Offline Hobbes

  • Commander
  • *****
  • Posts: 2101
  • Infiltration subroutine in progress
    • View Profile
Re: Mapscript Questions
« Reply #20 on: December 25, 2014, 07:26:50 pm »
this is the mapblock in question:

      - name: CBASE_05
        width: 10
        length: 20
        groups: 2
        revealedFloors: 1

Why it fails, and how can I make  it "not fail ever", since that mapblock is needed?

The issue might be the rectangular size of the map block. If you're not using rects to define the area on which CBASE_05 can be placed, then you risk that the game will randomly select a location for placement close to one edge of the map where the map block won't fit, and thus it will not be placed, causing the error.

Offline robin

  • Commander
  • *****
  • Posts: 1213
  • ULTIMATE ROOKIE
    • View Profile
Re: Mapscript Questions
« Reply #21 on: December 25, 2014, 09:27:08 pm »
The issue might be the rectangular size of the map block. If you're not using rects to define the area on which CBASE_05 can be placed, then you risk that the game will randomly select a location for placement close to one edge of the map where the map block won't fit, and thus it will not be placed, causing the error.
The original version of the script actually used rects, but it still failed. So I removed them to be sure the deal wasn't about them. Anyway, I still have to tray Falko's "size" suggestion, will post the results.

Offline robin

  • Commander
  • *****
  • Posts: 1213
  • ULTIMATE ROOKIE
    • View Profile
Re: Mapscript Questions
« Reply #22 on: January 01, 2015, 09:54:17 pm »
Code: [Select]
    - type: fillArea
      blocks: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]
      maxUses: [3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3]
i believe the blocks number corresponds with the position in the terrainlist
but do what is the number for the first entry in the list 0 or 1 ?
After some testing I believe the first number for "blocks" list is 0.

Offline Warboy1982

  • Administrator
  • Commander
  • *****
  • Posts: 2333
  • Developer
    • View Profile
Re: Mapscript Questions
« Reply #23 on: January 21, 2015, 10:53:01 pm »
The issue might be the rectangular size of the map block. If you're not using rects to define the area on which CBASE_05 can be placed, then you risk that the game will randomly select a location for placement close to one edge of the map where the map block won't fit, and thus it will not be placed, causing the error.

you sure? i thought i accounted for that?

Offline robin

  • Commander
  • *****
  • Posts: 1213
  • ULTIMATE ROOKIE
    • View Profile
Re: Mapscript Questions
« Reply #24 on: January 21, 2015, 10:55:29 pm »
Sometimes it works, sometimes it doesn't. I just want it to work all the time.
I'll try with the "size" thing.

Right now the script is like this:
  - type: TEMPLE
    commands:
    - type: addBlock
      groups: 2
      size: [1, 2]
      rects:
        - [0, 0, 1, 2]
        - [4, 0, 1, 2]
        - [0, 1, 1, 2]
        - [4, 1, 1, 2]
        - [0, 2, 1, 2]
        - [4, 2, 1, 2]
        - [0, 3, 1, 2]
        - [4, 3, 1, 2]
    - type: fillArea
      size: 2
      blocks: [0, 1, 2, 3, 4, 6, 9]
      maxUses: [1, 1, 1, 1, 1, 1, 1]
    - type: fillArea
      groups: 0
    - type: digTunnel
      direction: both
      tunnelData:
        level: 1
        MCDReplacements:
          - type: corner
            set: 1
            entry: 37
          - type: westWall
            set: 1
            entry: 32
          - type: northWall
            set: 1
            entry: 31
          - type: floor
            set: 1
            entry: 73

maps size is 50x50.

I think that changing "size: 2" to "size: [1, 2]" (see bolded part), did the trick.
« Last Edit: January 21, 2015, 10:58:52 pm by robin »

Offline Hobbes

  • Commander
  • *****
  • Posts: 2101
  • Infiltration subroutine in progress
    • View Profile
Re: Mapscript Questions
« Reply #25 on: January 21, 2015, 11:35:14 pm »
      rects:
        - [0, 0, 1, 2]
        - [4, 0, 1, 2]
        - [0, 1, 1, 2]
        - [4, 1, 1, 2]
        - [0, 2, 1, 2]
        - [4, 2, 1, 2]
        - [0, 3, 1, 2]
        - [4, 3, 1, 2]

This might be unnecessary, unless you want the 1x2 map to be specifically generated at those corners.

Offline Falko

  • Commander
  • *****
  • Posts: 802
    • View Profile
Re: Mapscript Questions
« Reply #26 on: January 21, 2015, 11:52:50 pm »
during my first look at the temple script robin posted
i stumbled on
Code: [Select]
      rects:
        - [0, 0, 1, 2]
        - [4, 0, 1, 2]
        - [0, 1, 1, 2]
        - [4, 1, 1, 2]
        - [0, 2, 1, 2]
        - [4, 2, 1, 2]
        - [0, 3, 1, 2]
        - [4, 3, 1, 2]
i had a short discussion with robin/warboy in irc and try to use this script as an example how "rects" works
the temple map is a 50x50 map
Code: [Select]
xxxxx
xxxxx
xxxxx
xxxxx
xxxxx
robin has a non quadratic mapblock (size: [1, 2]) he wants to place it on the edge of the map
i will reorder the rects here
Code: [Select]
      rects:
        - [0, 0, 1, 2]#A
        - [0, 1, 1, 2]#B
        - [0, 2, 1, 2]#C
        - [0, 3, 1, 2]#D
        - [4, 0, 1, 2]#E
        - [4, 1, 1, 2]#F
        - [4, 2, 1, 2]#G
        - [4, 3, 1, 2]#H
here two "maps" with the possible positions
Code: [Select]
AxxxE
AxxxE
CxxxG
CxxxG
xxxxx
Code: [Select]
xxxxx
BxxxF
BxxxF
DxxxH
DxxxH

the temple has 8 positions
and the rectlist with these 8 position works fine that way
but one can make it shorter
Code: [Select]
      rects:
        - [0, 0, 1, 5]#M
        - [4, 0, 1, 5]#N
the rects declares these ranges within the map
Code: [Select]
MxxxN
MxxxN
MxxxN
MxxxN
MxxxN

during the execution the script chooses at random one position within the rects where the block fits

hopefully my rambling did not lead to more confusion
« Last Edit: January 21, 2015, 11:56:02 pm by Falko »

Offline Warboy1982

  • Administrator
  • Commander
  • *****
  • Posts: 2333
  • Developer
    • View Profile
Re: Mapscript Questions
« Reply #27 on: January 22, 2015, 01:02:33 am »
your ramblings are correct, Falko.
i'd also like to point out that overlaps don't increase the likelihood of any position being picked.

so for example:
Code: [Select]
[0,0,4,4] A
[1,1,4,4] B

gives us:
Code: [Select]
AAAAx        xxxxx
AAAAx        xBBBB
AAAAx        xBBBB
AAAAx        xBBBB
xxxxx        xBBBB

which produces an overlap, C:
Code: [Select]
AAAAx
ACCCB
ACCCB
ACCCB
xBBBB

all positions marked A,B or C in the above example are equally likely
« Last Edit: January 22, 2015, 01:22:00 am by Warboy1982 »

Offline robin

  • Commander
  • *****
  • Posts: 1213
  • ULTIMATE ROOKIE
    • View Profile
Re: Mapscript Questions
« Reply #28 on: February 06, 2015, 02:44:09 pm »
Provided I understood correctly, Warboy said to me that the mapscript indicated in the alienDeployment (by the "script" entry)  is superseded by the one found in the terrain definition, the script in the deployments is intended to be a fallback if no scritp is defined in the terrain definition.

But then the alienDeployment itself dictates the size of the map, thus potentially making mapscipts defined in the terrains, inadequate.

I understand the terrains should bring their mapscripts from their definitions, so that multiple of them can be assigned to the same alienDeployments, each using its own rules to make the map.
But then again how would you deal with the fact that the terrain you want to use has a "wrong" script fro the map size of the Deployment? Make a clone terrain with a script tweaked for the size requested?

Offline Hobbes

  • Commander
  • *****
  • Posts: 2101
  • Infiltration subroutine in progress
    • View Profile
Re: Mapscript Questions
« Reply #29 on: February 06, 2015, 04:28:14 pm »
But then the alienDeployment itself dictates the size of the map, thus potentially making mapscipts defined in the terrains, inadequate.

There's a certain hierarchy involved:
* alienMissions define for each UFO listed its alienDeployment and ufo map.
* alienDeployments define the aliens present in the alienMission and their weapons, and set the battlescape size and define the number of civilians present. They can also be used to set the terrain type, if you want it to override the one assigned to the Geoscape texture
* terrains are used to define their Geoscape textures, MapDataSets, Mapblocks and civilian types used.
* Mapscripts are used to build the battlescape from the rules contained within.
* crafts/ufos define the mapDataSets and mapblocks used to place craft/UFOs - but this is only used if the mapscript has rules for placing them.

I haven't tried using the terrains to define the size of the map but to me it makes no sense to define it there since it will prevent the size of the battlescape to be dependent on any UFO placed. If Forest is set for 40x40 on terrains but it places a Battleship there then there won't be much space left.

Quote
I understand the terrains should bring their mapscripts from their definitions, so that multiple of them can be assigned to the same alienDeployments, each using its own rules to make the map.
But then again how would you deal with the fact that the terrain you want to use has a "wrong" script fro the map size of the Deployment? Make a clone terrain with a script tweaked for the size requested?

I'm currently using cloned terrains because some missions have UFOs assigned but I don't want them to be generated in the battlescape. But to have separate map sizes I'd do it through cloned alienDeployments, since you can adjust the number of aliens to the size. But this depends on what type of alienMission you're trying to design, because you'll need to use alienMission for those cloned deployments to run.

Cloning terrains brings the question of how to get the program to use them: you can assign them to specific textures, but you can't yet have multiple terrains assigned to a texture; you can also call them through alienDeployments, setting several random terrains, each with its determined size, and not having any size definitions on the alienDeployment entry (the wiki says that length/width/height isn't required for alienDeployments so it should work). 

The issue here is also designing the scripts to allow them to be used in different map sizes (which eliminates the need for cloned terrains) but the rules aren't too friendly on that matter. Placement of specific map blocks on the top right/left usually works without a problem on any battlescape size, but there will be issues if you need to place specific mapblocks on the bottom left/right.
« Last Edit: February 06, 2015, 04:34:25 pm by Hobbes »