Merge pull request #293 from ennorehling/feature/feature-json-terrains

Remove XML dependency for terrains, put it all in JSON
This commit is contained in:
Enno Rehling 2015-09-12 11:52:04 +02:00
commit e63767b99d
21 changed files with 711 additions and 363 deletions

View File

@ -1,6 +1,7 @@
{ {
"include": [ "include": [
"keywords.json" "keywords.json",
"e2/terrains.json"
], ],
"settings": { "settings": {
"game.id": 2, "game.id": 2,

View File

@ -20,8 +20,6 @@
<xi:include href="config://core/ships.xml"/> <xi:include href="config://core/ships.xml"/>
<xi:include href="config://core/common/buildings.xml"/> <xi:include href="config://core/common/buildings.xml"/>
<xi:include href="config://game/familiars.xml"/> <xi:include href="config://game/familiars.xml"/>
<xi:include href="config://core/terrains.xml"/>
<xi:include href="config://game/terrains.xml"/>
<xi:include href="config://game/artrewards.xml"/> <xi:include href="config://game/artrewards.xml"/>
<xi:include href="config://game/buildings.xml"/> <xi:include href="config://game/buildings.xml"/>
<xi:include href="config://core/calendar.xml"/> <xi:include href="config://core/calendar.xml"/>

296
conf/e2/terrains.json Normal file
View File

@ -0,0 +1,296 @@
{
"terrains": {
"ocean": {
"size": 100,
"flags": [ "swim", "sea", "sail", "fly" ]
},
"plain": {
"size": 10000,
"herbs": [ "h0", "h1", "h2", "h3", "h4", "h5" ],
"seed": 3,
"road": 50,
"flags": [ "land", "walk", "sail", "fly" ],
"production": {
"iron": {
"chance": 0.1,
"base": "5d8",
"div": "2d20+10",
"level": "2d4-1"
},
"stone": {
"chance": 0.15,
"base": "5d8",
"div": "2d30+20",
"level": "1d4"
},
"laen": {
"chance": 0.01,
"base": "1d4",
"div": "2d20+50",
"level": "1d4"
}
}
},
"swamp": {
"size": 2000,
"herbs": [ "h6", "h7", "h8" ],
"seed": 2,
"road": 75,
"flags": [ "land", "walk", "sail", "fly" ],
"production": {
"iron": {
"chance": 0.02,
"base": "5d8",
"div": "2d20+10",
"level": "2d4-1"
},
"stone": {
"chance": 0.02,
"base": "5d8",
"div": "2d30+20",
"level": "1d4"
},
"laen": {
"chance": 0.02,
"base": "1d4",
"div": "2d20+50",
"level": "1d4"
}
}
},
"desert": {
"size": 500,
"herbs": [ "h9", "h10", "h11" ],
"seed": 2,
"road": 100,
"flags": [ "land", "walk", "sail", "fly", "cavalry" ],
"production": {
"iron": {
"chance": 0.15,
"base": "5d8",
"div": "2d20+10",
"level": "2d4-1"
},
"stone": {
"chance": 0.25,
"base": "5d8",
"div": "2d30+20",
"level": "1d4"
},
"laen": {
"chance": 0.025,
"base": "1d4",
"div": "2d20+50",
"level": "1d4"
}
}
},
"highland": {
"size": 4000,
"herbs": [ "h12", "h13", "h14" ],
"seed": 2,
"road": 100,
"flags": [ "land", "walk", "sail", "fly", "cavalry" ],
"production": {
"iron": {
"chance": 0.15,
"base": "5d8",
"div": "2d20+10",
"level": "2d4-1"
},
"stone": {
"chance": 0.25,
"base": "5d8",
"div": "2d30+20",
"level": "1d4"
},
"laen": {
"chance": 0.025,
"base": "1d4",
"div": "2d20+50",
"level": "1d4"
}
}
},
"mountain": {
"size": 1000,
"herbs": [ "h15", "h16", "h17" ],
"seed": 2,
"road": 250,
"flags": [ "land", "walk", "sail", "fly" ],
"production": {
"iron": {
"chance": 1.0,
"base": "50",
"div": "50",
"level": "1"
},
"stone": {
"chance": 1.0,
"base": "100",
"div": "100",
"level": "1"
},
"laen": {
"chance": 0.05,
"base": "4",
"div": "100",
"level": "1"
}
}
},
"glacier": {
"size": 100,
"herbs": [ "h15", "h16", "h17" ],
"seed": 2,
"road": 250,
"flags": [ "arctic", "land", "walk", "sail", "fly" ],
"production": {
"iron": {
"chance": 1.0,
"base": "3",
"div": "50",
"level": "1"
},
"stone": {
"chance": 1.0,
"base": "2",
"div": "100",
"level": "1"
},
"laen": {
"chance": 0.05,
"base": "4",
"div": "100",
"level": "1"
}
}
},
"iceberg": {
"size": 100,
"herbs": [ "h18", "h19", "h20" ],
"flags": [ "arctic", "land", "walk", "sail", "fly" ],
"production": {
"iron": {
"chance": 0.9,
"base": "3",
"div": "50",
"level": "1"
},
"stone": {
"chance": 0.9,
"base": "2",
"div": "100",
"level": "1"
}
}
},
"iceberg_sleep": {
"size": 100,
"herbs": [ "h18", "h19", "h20" ],
"flags": [ "arctic", "land", "walk", "sail", "fly" ],
"production": {
"iron": {
"chance": 0.9,
"base": "3",
"div": "50",
"level": "1"
},
"stone": {
"chance": 0.9,
"base": "2",
"div": "100",
"level": "1"
},
"laen": {
"chance": 0.05,
"base": "4",
"div": "100",
"level": "1"
}
}
},
"firewall": {
"size": 100,
"road": 250,
"flags": [ "forbidden" ]
},
"fog": {
"flags": [ "walk", "fly" ]
},
"thickfog": {
"flags": [ "forbidden" ]
},
"volcano": {
"size": 500,
"road": 250,
"seed": 1,
"flags": [ "land", "walk", "sail", "fly" ],
"production": {
"iron": {
"chance": 0.5,
"level": 1,
"base": 50,
"div": 50
},
"stone": {
"chance": 0.5,
"level": 1,
"base": 100,
"div": 100
},
"laen": {
"chance": 0.075,
"level": 1,
"base": 4,
"div": 100
}
}
},
"activevolcano": {
"size": 500,
"road": 250,
"flags": [ "land", "walk", "sail", "fly" ],
"production": {
"iron": {
"chance": 0.5,
"level": 1,
"base": 50,
"div": 50
},
"stone": {
"chance": 0.5,
"level": 1,
"base": 100,
"div": 100
},
"laen": {
"chance": 0.075,
"level": 1,
"base": 4,
"div": 100
}
}
},
"hell": {
"flags": [ "land", "walk" ]
},
"hall1": {
"flags": [ "land", "walk", "sail" ]
},
"corridor1": {
"flags": [ "land", "walk", "sail" ]
},
"wall1": {
"flags": [ "forbidden" ]
},
"default": {
"size": 0,
"herbs": [],
"seed": 0,
"road": 0,
"flags": [ "land", "walk", "sail", "fly" ],
"production": {}
}
}
}

View File

@ -1,6 +1,7 @@
{ {
"include": [ "include": [
"keywords.json" "keywords.json",
"e3/terrains.json"
], ],
"settings": { "settings": {
"game.id": 3, "game.id": 3,

View File

@ -14,7 +14,6 @@
<xi:include href="config://game/ships.xml"/> <xi:include href="config://game/ships.xml"/>
<xi:include href="config://game/shipnames.xml"/> <xi:include href="config://game/shipnames.xml"/>
<xi:include href="config://game/terrains.xml"/>
<xi:include href="config://core/calendar.xml"/> <xi:include href="config://core/calendar.xml"/>
<xi:include href="config://game/items.xml" /> <xi:include href="config://game/items.xml" />
<xi:include href="config://game/strings.xml"/> <xi:include href="config://game/strings.xml"/>

235
conf/e3/terrains.json Normal file
View File

@ -0,0 +1,235 @@
{
"terrains": {
"ocean": {
"size": 100,
"flags": [ "sea", "swim", "sail", "fly" ]
},
"plain": {
"size": 4000,
"herbs": [ "h0", "h4" ],
"seed": 3,
"road": 50,
"flags": [ "forest", "cavalry", "land", "walk", "sail", "fly" ],
"production": {
"iron": {
"chance": 0.1,
"level": "2d4-1",
"base": "5d8",
"div": "2d20+10"
},
"stone": {
"chance": 0.15,
"level": "1d4",
"base": "5d8",
"div": "2d30+20"
},
"laen": {
"chance": 0.01,
"level": "1d4",
"base": "1d4",
"div": "2d20+50"
}
}
},
"swamp": {
"size": 1200,
"herbs": [ "h6", "h8" ],
"seed": 2,
"road": 75,
"flags": [ "land", "walk", "sail", "fly" ],
"production": {
"iron": {
"chance": 0.02,
"level": "2d4-1",
"base": "5d8",
"div": "2d20+10"
},
"stone": {
"chance": 0.02,
"level": "1d4",
"base": "5d8",
"div": "2d30+20"
},
"laen": {
"chance": 0.02,
"level": "1d4",
"base": "1d4",
"div": "2d20+50"
}
}
},
"desert": {
"size": 400,
"seed": 2,
"road": 75,
"flags": [ "cavalry", "land", "walk", "sail", "fly" ],
"herbs": [ "h9", "h11" ],
"production": {
"iron": {
"chance": 0.15,
"level": "2d4-1",
"base": "5d8",
"div": "2d20+10"
},
"stone": {
"chance": 0.25,
"level": "1d4",
"base": "5d8",
"div": "2d30+20"
},
"laen": {
"chance": 0.025,
"level": "1d4",
"base": "1d4",
"div": "2d20+50"
}
}
},
"highland": {
"size": 2300,
"seed": 2,
"road": 100,
"flags": [ "cavalry", "land", "walk", "sail", "fly" ],
"herbs": [ "h12", "h14" ],
"production": {
"iron": {
"chance": 0.15,
"level": "2d4-1",
"base": "5d8",
"div": "2d20+10"
},
"stone": {
"chance": 0.25,
"level": "1d4",
"base": "5d8",
"div": "2d30+20"
},
"laen": {
"chance": 0.025,
"level": "1d4",
"base": "1d4",
"div": "2d20+50"
}
}
},
"mountain": {
"size": 600,
"seed": 2,
"road": 250,
"flags": [ "land", "walk", "sail", "fly" ],
"herbs": [ "h15", "h17" ],
"production": {
"iron": {
"chance": 1.0,
"level": "1",
"base": "50",
"div": "50"
},
"stone": {
"chance": 1.0,
"level": "1",
"base": "100",
"div": "100"
},
"laen": {
"chance": 0.05,
"level": "1",
"base": "4",
"div": "100"
}
}
},
"glacier": {
"size": 150,
"seed": 2,
"road": 250,
"flags": [ "arctic", "land", "walk", "sail", "fly" ],
"herbs": [ "h18", "h20" ],
"production": {
"iron": {
"chance": 1.0,
"level": "1",
"base": "3",
"div": "50"
},
"stone": {
"chance": 1.0,
"level": "1",
"base": "2",
"div": "100"
},
"laen": {
"chance": 0.05,
"level": "1",
"base": "4",
"div": "100"
}
}
},
"packice": {
"flags": [ "arctic", "swim", "walk", "sail", "fly" ]
},
"firewall": {
"flags": [ "forbidden" ]
},
"volcano": {
"size": 400,
"seed": 1,
"road": 250,
"flags": [ "land", "walk", "sail", "fly" ],
"production": {
"iron": {
"chance": 0.5,
"level": "1",
"base": "50",
"div": "50"
},
"stone": {
"chance": 0.5,
"level": "1",
"base": "100",
"div": "100"
},
"laen": {
"chance": 0.075,
"level": "1",
"base": "4",
"div": "100"
}
}
},
"activevolcano": {
"size": 400,
"road": 250,
"flags": [ "land", "walk", "sail", "fly" ],
"production": {
"iron": {
"chance": 0.5,
"level": "1",
"base": "50",
"div": "50"
},
"stone": {
"chance": 0.5,
"level": "1",
"base": "100",
"div": "100"
},
"laen": {
"chance": 0.075,
"level": "1",
"base": "4",
"div": "100"
}
}
},
"default": {
"size": 0,
"herbs": [],
"seed": 0,
"road": 0,
"flags": [ "land", "walk", "sail", "fly" ],
"production": {}
}
}
}

View File

@ -1,6 +1,7 @@
{ {
"include": [ "include": [
"keywords.json" "keywords.json",
"e3/terrains.xml"
], ],
"settings": { "settings": {
"game.id": 4, "game.id": 4,

View File

@ -14,7 +14,6 @@
<xi:include href="config://game/ships.xml"/> <xi:include href="config://game/ships.xml"/>
<xi:include href="config://game/shipnames.xml"/> <xi:include href="config://game/shipnames.xml"/>
<xi:include href="config://game/terrains.xml"/>
<xi:include href="config://core/calendar.xml"/> <xi:include href="config://core/calendar.xml"/>
<xi:include href="config://game/items.xml" /> <xi:include href="config://game/items.xml" />
<xi:include href="config://game/strings.xml"/> <xi:include href="config://game/strings.xml"/>

View File

@ -1,84 +0,0 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<terrains>
<!-- defaults: walk="yes" sail="yes" fly="yes" swim="no" forest="no" sea="no" land="yes" forbidden="no" arctic="no" cavalry="no" -->
<terrain name="ocean" size="100" walk="no" swim="yes" land="no" sea="yes" />
<terrain name="plain" size="10000" road="50" forest="yes" cavalry="yes" seed="3">
<herb name="h0" />
<herb name="h1" />
<herb name="h2" />
<herb name="h3" />
<herb name="h4" />
<herb name="h5" />
<resource name="iron" chance="0.1" level="2d4-1" base="5d8" div="2d20+10" />
<resource name="stone" chance="0.15" level="1d4" base="5d8" div="2d30+20" />
<resource name="laen" chance="0.01" level="1d4" base="1d4" div="2d20+50" />
</terrain>
<terrain name="swamp" size="2000" road="75" seed="2">
<herb name="h6" />
<herb name="h7" />
<herb name="h8" />
<resource name="iron" chance="0.02" level="2d4-1" base="5d8" div="2d20+10" />
<resource name="stone" chance="0.02" level="1d4" base="5d8" div="2d30+20" />
<resource name="laen" chance="0.02" level="1d4" base="1d4" div="2d20+50" />
</terrain>
<terrain name="desert" size="500" road="100" cavalry="yes" seed="2">
<herb name="h9" />
<herb name="h10" />
<herb name="h11" />
<resource name="iron" chance="0.15" level="2d4-1" base="5d8" div="2d20+10" />
<resource name="stone" chance="0.25" level="1d4" base="5d8" div="2d30+20" />
<resource name="laen" chance="0.025" level="1d4" base="1d4" div="2d20+50" />
</terrain>
<terrain name="highland" size="4000" road="100" cavalry="yes" seed="2">
<herb name="h12" />
<herb name="h13" />
<herb name="h14" />
<resource name="iron" chance="0.15" level="2d4-1" base="5d8" div="2d20+10" />
<resource name="stone" chance="0.25" level="1d4" base="5d8" div="2d30+20" />
<resource name="laen" chance="0.025" level="1d4" base="1d4" div="2d20+50" />
</terrain>
<terrain name="mountain" size="1000" road="250" seed="2">
<herb name="h15" />
<herb name="h16" />
<herb name="h17" />
<resource name="iron" chance="1.0" level="1" base="50" div="50" />
<resource name="stone" chance="1.0" level="1" base="100" div="100" />
<resource name="laen" chance="0.05" level="1" base="4" div="100" />
</terrain>
<terrain name="glacier" size="100" road="250" arctic="yes" seed="2">
<herb name="h18" />
<herb name="h19" />
<herb name="h20" />
<resource name="iron" chance="1.0" level="1" base="3" div="50" />
<resource name="stone" chance="1.0" level="1" base="2" div="100" />
<resource name="laen" chance="0.05" level="1" base="4" div="100" />
</terrain>
<terrain name="iceberg_sleep" size="100" road="250" arctic="yes">
<herb name="h18" />
<herb name="h19" />
<herb name="h20" />
<resource name="iron" chance="0.9" level="1" base="3" div="50" />
<resource name="stone" chance="0.9" level="1" base="2" div="100" />
<resource name="laen" chance="0.05" level="1" base="4" div="100" />
</terrain>
<terrain name="iceberg" size="100" arctic="yes">
<herb name="h18" />
<herb name="h19" />
<herb name="h20" />
<resource name="iron" chance="0.9" level="1" base="3" div="50" />
<resource name="stone" chance="0.9" level="1" base="2" div="100" />
</terrain>
<terrain name="firewall" size="100" road="250" land="no" walk="no" sail="no" fly="no" forbidden="yes" />
<terrain name="fog" sail="no" land="no" size="0" />
<terrain name="thickfog" forbidden="yes" sail="no" walk="no" fly="no" land="no" size="0" />
<terrain name="volcano" size="500" road="250" seed="1">
<resource name="iron" chance="0.5" level="1" base="50" div="50" />
<resource name="stone" chance="0.5" level="1" base="100" div="100" />
<resource name="laen" chance="0.075" level="1" base="4" div="100" />
</terrain>
<terrain name="activevolcano" size="500" road="250">
<resource name="iron" chance="0.5" level="1" base="50" div="50" />
<resource name="stone" chance="0.5" level="1" base="100" div="100" />
<resource name="laen" chance="0.075" level="1" base="4" div="100" />
</terrain>
</terrains>

View File

@ -1,61 +0,0 @@
<?xml version="1.0" ?>
<terrains>
<!-- defaults: build="yes" walk="yes" sail="yes" fly="yes" swim="no" forest="no" sea="no" land="yes" forbidden="no" arctic="no" cavalry="no" size="0" -->
<terrain name="ocean" size="100" walk="no" swim="yes" land="no" sea="yes" />
<terrain name="plain" size="4000" road="50" forest="yes" cavalry="yes" seed="3">
<herb name="h0" />
<herb name="h4" />
<resource name="iron" chance="0.1" level="2d4-1" base="5d8" div="2d20+10" />
<resource name="stone" chance="0.15" level="1d4" base="5d8" div="2d30+20" />
<resource name="laen" chance="0.01" level="1d4" base="1d4" div="2d20+50" />
</terrain>
<terrain name="swamp" size="1200" road="75" seed="2">
<herb name="h6" />
<herb name="h8" />
<resource name="iron" chance="0.02" level="2d4-1" base="5d8" div="2d20+10" />
<resource name="stone" chance="0.02" level="1d4" base="5d8" div="2d30+20" />
<resource name="laen" chance="0.02" level="1d4" base="1d4" div="2d20+50" />
</terrain>
<terrain name="desert" size="400" road="100" cavalry="yes" seed="2">
<herb name="h9" />
<herb name="h11" />
<resource name="iron" chance="0.15" level="2d4-1" base="5d8" div="2d20+10" />
<resource name="stone" chance="0.25" level="1d4" base="5d8" div="2d30+20" />
<resource name="laen" chance="0.025" level="1d4" base="1d4" div="2d20+50" />
</terrain>
<terrain name="highland" size="2300" road="100" cavalry="yes" seed="2">
<herb name="h12" />
<herb name="h14" />
<resource name="iron" chance="0.15" level="2d4-1" base="5d8" div="2d20+10" />
<resource name="stone" chance="0.25" level="1d4" base="5d8" div="2d30+20" />
<resource name="laen" chance="0.025" level="1d4" base="1d4" div="2d20+50" />
</terrain>
<terrain name="mountain" size="600" road="250" seed="2">
<herb name="h15" />
<herb name="h17" />
<resource name="iron" chance="1.0" level="1" base="50" div="50" />
<resource name="stone" chance="1.0" level="1" base="100" div="100" />
<resource name="laen" chance="0.05" level="1" base="4" div="100" />
</terrain>
<terrain name="glacier" size="150" road="250" arctic="yes" seed="2">
<herb name="h18" />
<herb name="h20" />
<resource name="iron" chance="1.0" level="1" base="3" div="50" />
<resource name="stone" chance="1.0" level="1" base="2" div="100" />
<resource name="laen" chance="0.05" level="1" base="4" div="100" />
</terrain>
<terrain name="packice" land="no" arctic="yes" swim="yes"/>
<terrain name="firewall" road="250" land="no" walk="no" sail="no" fly="no" forbidden="yes" />
<terrain name="fog" sail="no" land="no" />
<terrain name="thickfog" forbidden="yes" sail="no" walk="no" fly="no" land="no" />
<terrain name="volcano" size="400" road="250" seed="1">
<resource name="iron" chance="0.5" level="1" base="50" div="50" />
<resource name="stone" chance="0.5" level="1" base="100" div="100" />
<resource name="laen" chance="0.075" level="1" base="4" div="100" />
</terrain>
<terrain name="activevolcano" size="400" road="250">
<resource name="iron" chance="0.5" level="1" base="50" div="50" />
<resource name="stone" chance="0.5" level="1" base="100" div="100" />
<resource name="laen" chance="0.075" level="1" base="4" div="100" />
</terrain>
</terrains>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" ?>
<terrains>
<!-- used by the experimental dungeon -->
<terrain name="hell" fly="no" sail="no" size="0" land="no"/>
<!-- used for the museum only -->
<terrain name="hall1" fly="no" size="0" />
<terrain name="corridor1" fly="no" size="0" />
<terrain name="wall1" sail="no" walk="no" fly="no" forbidden="yes" size="0" />
</terrains>

View File

@ -1,57 +0,0 @@
<?xml version="1.0" ?>
<terrains>
<!-- defaults: walk="yes" sail="yes" fly="yes" swim="no" forest="no" sea="no" land="yes" forbidden="no" arctic="no" cavalry="no" size="0" -->
<terrain name="ocean" size="100" walk="no" swim="yes" land="no" sea="yes" />
<terrain name="plain" size="4000" road="50" forest="yes" cavalry="yes" seed="3">
<resource name="iron" chance="0.1" level="2d4-1" base="5d8" div="2d20+10" />
<resource name="stone" chance="0.15" level="1d4" base="5d8" div="2d30+20" />
<resource name="laen" chance="0.01" level="1d4" base="1d4" div="2d20+50" />
</terrain>
<terrain name="swamp" size="1200" road="75" seed="2">
<resource name="iron" chance="0.02" level="2d4-1" base="5d8" div="2d20+10" />
<resource name="stone" chance="0.02" level="1d4" base="5d8" div="2d30+20" />
<resource name="laen" chance="0.02" level="1d4" base="1d4" div="2d20+50" />
</terrain>
<terrain name="desert" size="400" road="100" cavalry="yes" seed="2">
<resource name="iron" chance="0.15" level="2d4-1" base="5d8" div="2d20+10" />
<resource name="stone" chance="0.25" level="1d4" base="5d8" div="2d30+20" />
<resource name="laen" chance="0.025" level="1d4" base="1d4" div="2d20+50" />
</terrain>
<terrain name="highland" size="2300" road="100" cavalry="yes" seed="2">
<resource name="iron" chance="0.15" level="2d4-1" base="5d8" div="2d20+10" />
<resource name="stone" chance="0.25" level="1d4" base="5d8" div="2d30+20" />
<resource name="laen" chance="0.025" level="1d4" base="1d4" div="2d20+50" />
</terrain>
<terrain name="mountain" size="600" road="250" seed="2">
<resource name="iron" chance="1.0" level="1" base="50" div="50" />
<resource name="stone" chance="1.0" level="1" base="100" div="100" />
<resource name="laen" chance="0.05" level="1" base="4" div="100" />
</terrain>
<terrain name="glacier" size="150" road="250" arctic="yes" seed="2">
<resource name="iron" chance="1.0" level="1" base="3" div="50" />
<resource name="stone" chance="1.0" level="1" base="2" div="100" />
<resource name="laen" chance="0.05" level="1" base="4" div="100" />
</terrain>
<terrain name="iceberg_sleep" size="150" road="250" arctic="yes">
<resource name="iron" chance="0.9" level="1" base="3" div="50" />
<resource name="stone" chance="0.9" level="1" base="2" div="100" />
<resource name="laen" chance="0.05" level="1" base="4" div="100" />
</terrain>
<terrain name="iceberg" size="150" arctic="yes">
<resource name="iron" chance="0.9" level="1" base="3" div="50" />
<resource name="stone" chance="0.9" level="1" base="2" div="100" />
</terrain>
<terrain name="firewall" road="250" land="no" walk="no" sail="no" fly="no" forbidden="yes" />
<terrain name="fog" sail="no" land="no" />
<terrain name="thickfog" forbidden="yes" sail="no" walk="no" fly="no" land="no" />
<terrain name="volcano" size="400" road="250" seed="1">
<resource name="iron" chance="0.5" level="1" base="50" div="50" />
<resource name="stone" chance="0.5" level="1" base="100" div="100" />
<resource name="laen" chance="0.075" level="1" base="4" div="100" />
</terrain>
<terrain name="activevolcano" size="400" road="250">
<resource name="iron" chance="0.5" level="1" base="50" div="50" />
<resource name="stone" chance="0.5" level="1" base="100" div="100" />
<resource name="laen" chance="0.075" level="1" base="4" div="100" />
</terrain>
</terrains>

View File

@ -54,6 +54,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* libc includes */ /* libc includes */
#include <assert.h> #include <assert.h>
#include <errno.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -179,10 +180,15 @@ static void rt_register(resource_type * rtype)
resource_type *rt_get_or_create(const char *name) { resource_type *rt_get_or_create(const char *name) {
resource_type *rtype = rt_find(name); resource_type *rtype = rt_find(name);
if (!rtype) { if (!rtype) {
rtype = (resource_type *)calloc(sizeof(resource_type), 1); rtype = calloc(1, sizeof(resource_type));
if (!rtype) {
perror("resource_type allocation failed");
}
else {
rtype->_name = _strdup(name); rtype->_name = _strdup(name);
rt_register(rtype); rt_register(rtype);
} }
}
return rtype; return rtype;
} }

View File

@ -185,6 +185,39 @@ static void json_construction(cJSON *json, construction **consp) {
*consp = cons; *consp = cons;
} }
static void json_terrain_production(cJSON *json, terrain_production *prod) {
assert(json->type == cJSON_Object);
cJSON *child;
for (child = json->child; child; child = child->next) {
switch (child->type) {
case cJSON_String:
if (strcmp(child->string, "base") == 0) {
prod->base = _strdup(child->valuestring);
}
else if (strcmp(child->string, "level") == 0) {
prod->startlevel = _strdup(child->valuestring);
}
else if (strcmp(child->string, "div") == 0) {
prod->divisor = _strdup(child->valuestring);
}
else {
log_error("terrain_production %s contains unknown attribute %s", json->string, child->string);
}
break;
case cJSON_Number:
if (strcmp(child->string, "chance") == 0) {
prod->chance = (float)child->valuedouble;
}
else {
log_error("terrain_production %s contains unknown attribute %s", json->string, child->string);
}
break;
default:
log_error("terrain_production %s contains unknown attribute %s", json->string, child->string);
}
}
}
static void json_terrain(cJSON *json, terrain_type *ter) { static void json_terrain(cJSON *json, terrain_type *ter) {
cJSON *child; cJSON *child;
if (json->type != cJSON_Object) { if (json->type != cJSON_Object) {
@ -193,6 +226,29 @@ static void json_terrain(cJSON *json, terrain_type *ter) {
} }
for (child = json->child; child; child = child->next) { for (child = json->child; child; child = child->next) {
switch (child->type) { switch (child->type) {
case cJSON_Object:
if (strcmp(child->string, "production") == 0) {
cJSON *entry;
int size = cJSON_GetArraySize(child);
if (size > 0) {
int n;
ter->production = (terrain_production *)calloc(size + 1, sizeof(terrain_production));
ter->production[size].type = 0;
for (n = 0, entry = child->child; entry; entry = entry->next, ++n) {
ter->production[n].type = rt_get_or_create(entry->string);
if (entry->type != cJSON_Object) {
log_error("terrain %s contains invalid production %s", json->string, entry->string);
}
else {
json_terrain_production(entry, ter->production + n);
}
}
}
}
else {
log_error("terrain %s contains unknown attribute %s", json->string, child->string);
}
break;
case cJSON_Array: case cJSON_Array:
if (strcmp(child->string, "flags") == 0) { if (strcmp(child->string, "flags") == 0) {
const char * flags[] = { const char * flags[] = {
@ -200,6 +256,32 @@ static void json_terrain(cJSON *json, terrain_type *ter) {
}; };
ter->flags = json_flags(child, flags); ter->flags = json_flags(child, flags);
} }
else if (strcmp(child->string, "herbs") == 0) {
cJSON *entry;
int size = cJSON_GetArraySize(child);
if (size > 0) {
int n;
ter->herbs = malloc(sizeof(const item_type *) * (size + 1));
ter->herbs[size] = 0;
for (n = 0, entry = child->child; entry; entry = entry->next) {
ter->herbs[n++] = it_get_or_create(rt_get_or_create(entry->valuestring));
}
}
}
else {
log_error("terrain %s contains unknown attribute %s", json->string, child->string);
}
break;
case cJSON_Number:
if (strcmp(child->string, "size") == 0) {
ter->size = child->valueint;
}
else if (strcmp(child->string, "road") == 0) {
ter->max_road = (short)child->valueint;
}
else if (strcmp(child->string, "seed") == 0) {
ter->distribution = (short)child->valueint;
}
else { else {
log_error("terrain %s contains unknown attribute %s", json->string, child->string); log_error("terrain %s contains unknown attribute %s", json->string, child->string);
} }
@ -702,14 +784,20 @@ static void json_include(cJSON *json) {
fclose(F); fclose(F);
config = cJSON_Parse(data); config = cJSON_Parse(data);
free(data); free(data);
if (config) {
json_config(config); json_config(config);
cJSON_Delete(config); cJSON_Delete(config);
} }
else {
log_error("invalid JSON, could not parse %s", child->valuestring);
}
}
} }
} }
void json_config(cJSON *json) { void json_config(cJSON *json) {
cJSON *child; cJSON *child;
assert(json);
if (json->type != cJSON_Object) { if (json->type != cJSON_Object) {
log_error("config is not a json object: %d", json->type); log_error("config is not a json object: %d", json->type);
return; return;
@ -751,6 +839,7 @@ void json_config(cJSON *json) {
} }
else if (strcmp(child->string, "terrains") == 0) { else if (strcmp(child->string, "terrains") == 0) {
json_terrains(child); json_terrains(child);
init_terrains();
} }
else { else {
log_error("config contains unknown attribute %s", child->string); log_error("config contains unknown attribute %s", child->string);

View File

@ -389,7 +389,13 @@ static void test_configs(CuTest * tc)
static void test_terrains(CuTest * tc) static void test_terrains(CuTest * tc)
{ {
const char * data = "{\"terrains\": { \"plain\" : { \"flags\" : [ \"land\", \"fly\", \"walk\" ] } }}"; const char * data = "{\"terrains\": { \"plain\" : { "
"\"herbs\": [ \"h0\", \"h1\" ], "
"\"production\": { \"stone\": { \"chance\": 0.1, \"base\": \"1d4\", \"div\": \"1d5\", \"level\": \"1d6\" }, \"iron\": {} }, "
"\"size\": 4000, "
"\"road\": 50, "
"\"seed\": 3, "
"\"flags\" : [ \"forbidden\", \"arctic\", \"cavalry\", \"sea\", \"forest\", \"land\", \"sail\", \"fly\", \"swim\", \"walk\" ] } }}";
const terrain_type *ter; const terrain_type *ter;
cJSON *json = cJSON_Parse(data); cJSON *json = cJSON_Parse(data);
@ -401,7 +407,23 @@ static void test_terrains(CuTest * tc)
json_config(json); json_config(json);
ter = get_terrain("plain"); ter = get_terrain("plain");
CuAssertPtrNotNull(tc, ter); CuAssertPtrNotNull(tc, ter);
CuAssertIntEquals(tc, ter->flags, LAND_REGION | FLY_INTO | WALK_INTO); CuAssertIntEquals(tc, ARCTIC_REGION | LAND_REGION | SEA_REGION | FOREST_REGION | CAVALRY_REGION | FORBIDDEN_REGION | FLY_INTO | WALK_INTO | SWIM_INTO | SAIL_INTO, ter->flags);
CuAssertIntEquals(tc, 4000, ter->size);
CuAssertIntEquals(tc, 50, ter->max_road);
CuAssertIntEquals(tc, 3, ter->distribution);
CuAssertPtrNotNull(tc, ter->herbs);
CuAssertPtrEquals(tc, rt_get_or_create("h0"), ter->herbs[0]->rtype);
CuAssertPtrEquals(tc, rt_get_or_create("h1"), ter->herbs[1]->rtype);
CuAssertPtrEquals(tc, 0, (void *)ter->herbs[2]);
CuAssertPtrNotNull(tc, ter->name); // anything named "plain" uses plain_name()
CuAssertPtrNotNull(tc, ter->production);
CuAssertPtrEquals(tc, rt_get_or_create("stone"), (resource_type *)ter->production[0].type);
CuAssertDblEquals(tc, 0.1, ter->production[0].chance, 0.01);
CuAssertStrEquals(tc, "1d4", ter->production[0].base);
CuAssertStrEquals(tc, "1d5", ter->production[0].divisor);
CuAssertStrEquals(tc, "1d6", ter->production[0].startlevel);
CuAssertPtrEquals(tc, rt_get_or_create("iron"), (resource_type *)ter->production[1].type);
CuAssertPtrEquals(tc, 0, (void *)ter->production[2].type);
test_cleanup(); test_cleanup();
} }

View File

@ -1119,14 +1119,19 @@ void terraform_region(region * r, const terrain_type * terrain)
} }
if (oldterrain == NULL || terrain->size != oldterrain->size) { if (oldterrain == NULL || terrain->size != oldterrain->size) {
int horses = 0, trees = 0;
if (terrain->size>0) {
horses = rng_int() % (terrain->size / 50);
trees = terrain->size * (30 + rng_int() % 40) / 1000;
}
if (terrain == newterrain(T_PLAIN)) { if (terrain == newterrain(T_PLAIN)) {
rsethorses(r, rng_int() % (terrain->size / 50)); rsethorses(r, horses);
if (rng_int() % 100 < 40) { if (chance(0.4)) {
rsettrees(r, 2, terrain->size * (30 + rng_int() % 40) / 1000); rsettrees(r, 2, trees);
} }
} }
else if (chance(0.2)) { else if (trees>0 && chance(0.2)) {
rsettrees(r, 2, terrain->size * (30 + rng_int() % 40) / 1000); rsettrees(r, 2, trees);
} }
else { else {
rsettrees(r, 2, 0); rsettrees(r, 2, 0);
@ -1146,7 +1151,7 @@ void terraform_region(region * r, const terrain_type * terrain)
/** ENNO: /** ENNO:
* ich denke, das das hier nicht sein sollte. * ich denke, das das hier nicht sein sollte.
* statt dessen sollte ein attribut an der region sein, das das erledigt, * statt dessen sollte ein attribut an der region sein, dass das erledigt,
* egal ob durch den spell oder anderes angelegt. * egal ob durch den spell oder anderes angelegt.
**/ **/
#include "curse.h" #include "curse.h"

View File

@ -59,10 +59,18 @@ static terrain_type *registered_terrains;
void free_terrains(void) void free_terrains(void)
{ {
while (registered_terrains) { while (registered_terrains) {
int n;
terrain_type * t = registered_terrains; terrain_type * t = registered_terrains;
registered_terrains = t->next; registered_terrains = t->next;
free(t->_name); free(t->_name);
if (t->production) {
for (n = 0; t->production[n].type; ++n) {
free(t->production[n].base);
free(t->production[n].divisor);
free(t->production[n].startlevel);
}
free(t->production); free(t->production);
}
free(t); free(t);
} }
} }

View File

@ -51,9 +51,9 @@ extern "C" {
typedef struct terrain_production { typedef struct terrain_production {
const struct resource_type *type; const struct resource_type *type;
const char *startlevel; char *startlevel;
const char *base; char *base;
const char *divisor; char *divisor;
float chance; float chance;
} terrain_production; } terrain_production;

View File

@ -1883,131 +1883,6 @@ static int parse_races(xmlDocPtr doc)
return 0; return 0;
} }
static int parse_terrains(xmlDocPtr doc)
{
xmlXPathContextPtr xpath;
xmlXPathObjectPtr terrains;
xmlNodeSetPtr nodes;
int i;
xpath = xmlXPathNewContext(doc);
/* reading eressea/terrains/terrain */
terrains =
xmlXPathEvalExpression(BAD_CAST "/eressea/terrains/terrain", xpath);
nodes = terrains->nodesetval;
for (i = 0; i != nodes->nodeNr; ++i) {
xmlNodePtr node = nodes->nodeTab[i];
terrain_type *terrain;
xmlChar *propValue;
xmlXPathObjectPtr xpathChildren;
xmlNodeSetPtr children;
propValue = xmlGetProp(node, BAD_CAST "name");
assert(propValue != NULL);
terrain = get_or_create_terrain((const char *)propValue);
xmlFree(propValue);
terrain->max_road = (short)xml_ivalue(node, "road", 0);
assert(terrain->max_road >= 0);
terrain->size = xml_ivalue(node, "size", 0);
if (xml_bvalue(node, "forbidden", false))
terrain->flags |= FORBIDDEN_REGION;
else {
if (xml_bvalue(node, "fly", true))
terrain->flags |= FLY_INTO;
if (xml_bvalue(node, "sail", true))
terrain->flags |= SAIL_INTO;
if (xml_bvalue(node, "walk", true))
terrain->flags |= WALK_INTO;
if (xml_bvalue(node, "swim", false))
terrain->flags |= SWIM_INTO;
if (xml_bvalue(node, "cavalry", false))
terrain->flags |= CAVALRY_REGION;
}
if (xml_bvalue(node, "sea", false))
terrain->flags |= SEA_REGION;
if (xml_bvalue(node, "arctic", false))
terrain->flags |= ARCTIC_REGION;
if (xml_bvalue(node, "land", true))
terrain->flags |= LAND_REGION;
if (xml_bvalue(node, "forest", false))
terrain->flags |= FOREST_REGION;
terrain->distribution = (short)xml_ivalue(node, "seed", 0);
xpath->node = node;
xpathChildren = xmlXPathEvalExpression(BAD_CAST "herb", xpath);
children = xpathChildren->nodesetval;
if (children->nodeNr > 0) {
int k;
terrain->herbs = malloc((children->nodeNr + 1) * sizeof(item_type *));
terrain->herbs[children->nodeNr] = NULL;
for (k = 0; k != children->nodeNr; ++k) {
xmlNodePtr nodeHerb = children->nodeTab[k];
const struct resource_type *rtype;
propValue = xmlGetProp(nodeHerb, BAD_CAST "name");
assert(propValue != NULL);
rtype = rt_find((const char *)propValue);
assert(rtype != NULL && rtype->itype != NULL
&& fval(rtype->itype, ITF_HERB));
terrain->herbs[k] = rtype->itype;
xmlFree(propValue);
}
}
xmlXPathFreeObject(xpathChildren);
xpath->node = node;
xpathChildren = xmlXPathEvalExpression(BAD_CAST "resource", xpath);
children = xpathChildren->nodesetval;
if (children->nodeNr > 0) {
int k;
terrain->production =
malloc((children->nodeNr + 1) * sizeof(terrain_production));
terrain->production[children->nodeNr].type = NULL;
for (k = 0; k != children->nodeNr; ++k) {
xmlNodePtr nodeProd = children->nodeTab[k];
propValue = xmlGetProp(nodeProd, BAD_CAST "name");
assert(propValue != NULL);
terrain->production[k].type = rt_find((const char *)propValue);
assert(terrain->production[k].type);
xmlFree(propValue);
propValue = xmlGetProp(nodeProd, BAD_CAST "level");
assert(propValue);
terrain->production[k].startlevel = _strdup((const char *)propValue);
xmlFree(propValue);
propValue = xmlGetProp(nodeProd, BAD_CAST "base");
assert(propValue);
terrain->production[k].base = _strdup((const char *)propValue);
xmlFree(propValue);
propValue = xmlGetProp(nodeProd, BAD_CAST "div");
assert(propValue);
terrain->production[k].divisor = _strdup((const char *)propValue);
xmlFree(propValue);
terrain->production[k].chance =
(float)xml_fvalue(nodeProd, "chance", 1.0);
}
}
xmlXPathFreeObject(xpathChildren);
}
xmlXPathFreeObject(terrains);
xmlXPathFreeContext(xpath);
init_terrains();
return 0;
}
static int parse_messages(xmlDocPtr doc) static int parse_messages(xmlDocPtr doc)
{ {
xmlXPathContextPtr xpath; xmlXPathContextPtr xpath;
@ -2287,7 +2162,6 @@ void register_xmlreader(void)
xml_register_callback(parse_resources); xml_register_callback(parse_resources);
xml_register_callback(parse_rules); xml_register_callback(parse_rules);
xml_register_callback(parse_terrains); /* requires resources */
xml_register_callback(parse_buildings); /* requires resources */ xml_register_callback(parse_buildings); /* requires resources */
xml_register_callback(parse_ships); /* requires terrains */ xml_register_callback(parse_ships); /* requires terrains */
xml_register_callback(parse_spells); /* requires resources */ xml_register_callback(parse_spells); /* requires resources */

View File

@ -215,6 +215,31 @@ static void test_walkingcapacity(CuTest *tc) {
test_cleanup(); test_cleanup();
} }
static void test_is_guarded(CuTest *tc) {
unit *u1, *u2;
region *r;
race *rc;
test_cleanup();
rc = rc_get_or_create("dragon");
rc->flags |= RCF_UNARMEDGUARD;
r = test_create_region(0, 0, 0);
u1 = test_create_unit(test_create_faction(0), r);
u2 = test_create_unit(test_create_faction(rc), r);
CuAssertPtrEquals(tc, 0, is_guarded(r, u1, GUARD_TRAVELTHRU));
CuAssertPtrEquals(tc, 0, is_guarded(r, u1, GUARD_PRODUCE));
CuAssertPtrEquals(tc, 0, is_guarded(r, u1, GUARD_TREES));
CuAssertPtrEquals(tc, 0, is_guarded(r, u1, GUARD_MINING));
guard(u2, GUARD_MINING | GUARD_PRODUCE);
CuAssertIntEquals(tc, GUARD_CREWS | GUARD_LANDING | GUARD_TRAVELTHRU | GUARD_TAX | GUARD_PRODUCE | GUARD_RECRUIT, guard_flags(u2));
CuAssertPtrEquals(tc, 0, is_guarded(r, u1, GUARD_TRAVELTHRU));
CuAssertPtrEquals(tc, 0, is_guarded(r, u1, GUARD_TREES));
CuAssertPtrEquals(tc, 0, is_guarded(r, u1, GUARD_MINING));
CuAssertPtrEquals(tc, u2, is_guarded(r, u1, GUARD_PRODUCE));
test_cleanup();
}
CuSuite *get_move_suite(void) CuSuite *get_move_suite(void)
{ {
CuSuite *suite = CuSuiteNew(); CuSuite *suite = CuSuiteNew();
@ -226,5 +251,6 @@ CuSuite *get_move_suite(void)
SUITE_ADD_TEST(suite, test_ship_has_harbormaster_contact); SUITE_ADD_TEST(suite, test_ship_has_harbormaster_contact);
SUITE_ADD_TEST(suite, test_ship_has_harbormaster_ally); SUITE_ADD_TEST(suite, test_ship_has_harbormaster_ally);
SUITE_ADD_TEST(suite, test_ship_has_harbormaster_same_faction); SUITE_ADD_TEST(suite, test_ship_has_harbormaster_same_faction);
SUITE_ADD_TEST(suite, test_is_guarded);
return suite; return suite;
} }