fk
Topic Opener
Joined:
2013-07-30, 22:58 UTC+2.0
Posts: 150
At home in WL-forums
|
Posted at:
2014-02-17, 23:00 UTC+1.0
This script builds both a woodcutters house and a foresters house close to each other in the area around the castle with the most trees and with enough room for these two buildings, this in addition to the buildings that were already included in Castle Village. It works for the Atlanteans only.
The code divides the area around the castle in 7 regions, and tries to select the most suitable region for the buildings.
The gameplay is actually much better if the AI players start with more buildings than in the default set up. Problem was that especially the Atlanteans use enormous amounts of trunks and may often get stuck before they have finished a woodcutters house and a foresters house.
(The code is still messy, but functional:)
-- =========================================================
-- Wood Village Starting Conditions
--
-- Fair use policy
-- =========================================================
set_textdomain("tribe_atlanteans")
-- =========================== infrastructure =====================
--(derived from infrastructure.lua)
-- Returns last building:
function _prefilled_buildings(p, ...)
local building
for idx,bdescr in ipairs({...}) do
b = p:place_building(bdescr[1], wl.Game().map:get_field(bdescr[2],
bdescr[3]), false, true)
building = b
-- Fill with workers
if b.valid_workers then b:set_workers(b.valid_workers) end
if bdescr.workers then b:set_workers(bdescr.workers) end
-- Fill with soldiers
if b.max_soldiers and b.set_soldiers then
if bdescr.soldiers then
b:set_soldiers(bdescr.soldiers)
else
b:set_soldiers({0,0,0,0}, b.max_soldiers)
end
elseif bdescr.soldiers then -- Must be a warehouse
b:set_soldiers(bdescr.soldiers)
end
-- Fill with wares if this is requested
if bdescr.wares then b:set_wares(bdescr.wares) end
end
return building
end
function _place_building_in_region(
plr, building, fields, gargs
)
local idx
local f
local args = gargs or {}
local req_suitability = args.req_suitability or 1
while #fields > 0 do
local idx = math.random(#fields)
local f = fields[idx]
if plr:get_suitability(building, f) >= req_suitability then
args[1] = building
args[2] = f.x
args[3] = f.y
return _prefilled_buildings(plr, args)
end
table.remove(fields, idx)
end
error(string.format(
"Could not find a suitable position for building '%s' for player %i",
building, plr.number)
)
end
-- =========================== scan for objects ====================
function count_trees(fld)
local imm = fld.immovable
local amount = 0
if imm then
local name = string.sub(imm.name, 1, 4)
if name == "tree" then
amount = 1
end
end
return amount
end
function count_trees_in_region(area)
local i = 1
local trees = 0
while i <= #area do
trees = trees + count_trees(area[i])
i = i + 1
end
return trees
end
-- =============== divide region(12) in seven region(4) ============
function asterisk(fld)
local point = {
fld,
fld.rn.rn.rn.rn.rn.rn.rn.rn,
fld.brn.brn.brn.brn.brn.brn.brn.brn,
fld.trn.trn.trn.trn.trn.trn.trn.trn,
fld.ln.ln.ln.ln.ln.ln.ln.ln,
fld.bln.bln.bln.bln.bln.bln.bln.bln,
fld.tln.tln.tln.tln.tln.tln.tln.tln
}
return point
end
-- ============================ duo sort ======================
function sort(array1, array2)
local i
local done = false
while not done do
i = 1
done = true
while i < #array1 do
if array1[i] < array1[i + 1] then
local a
a = array1[i]
array1[i] = array1[i + 1]
array1[i + 1] = a
a = array2[i]
array2[i] = array2[i + 1]
array2[i + 1] = a
done = false
end
i = i + 1
end
end
return array1, array2
end
-- ============================ ========================
function get_suitability_in_region(plr, building, fields)
local flag = false
local i = 1
while i <= #fields do
if plr:get_suitability(building, fields[i]) >= 1 then
flag = true
break
end
i = i + 1
end
return flag
end
-- ============================ main ======================
return {
name = _ "Wood Village",
func = function(plr, shared_in_start)
local sf = wl.Game().map.player_slots[plr.number].starting_field
if shared_in_start then
sf = shared_in_start
else
plr:allow_workers("all")
end
local h = plr:place_building("castle", sf, false, true)
h:set_soldiers{[{0,0,0,0}] = 12}
local point = asterisk(sf)
local array1 = {}
local array2 = {}
local i = 1
local j = 1
local m = 0
local p
while i <= #point do
p = count_trees_in_region(point[i]:region(4))
array1[i] = p
array2[i] = point[i]
if p > m then
m = p
j = i
end
i = i + 1
end
sort(array1, array2)
local chop
local drop
local building
i = 1
while i <= #array1 do
chop = get_suitability_in_region(plr, "woodcutters_house",
array2[i]:region(4))
if chop then
building = _place_building_in_region(plr, "woodcutters_house",
array2[i]:region(4))
drop = get_suitability_in_region(plr, "foresters_house", array2[i]:region(4))
if building and building.flag then building.flag:remove() end
if drop then
_place_building_in_region(plr, "woodcutters_house", array2[i]:region(4))
_place_building_in_region(plr, "foresters_house", array2[i]:region(4))
break
end
end
i = i + 1
end
if not pcall(function()
_place_building_in_region(plr, "warehouse", sf:region(7), {
wares = {
diamond = 7,
ironore = 5,
quartz = 9,
stone = 50,
spideryarn = 9,
trunk = 13,
goldyarn = 6,
planks = 45,
spidercloth = 5,
blackroot = 5,
blackrootflour = 12,
corn = 5,
cornflour = 12,
fish = 3,
meat = 3,
water = 12,
bakingtray = 2,
bucket = 2,
fire_tongs = 2,
fishing_net = 4,
hammer = 11,
hunting_bow = 1,
milking_tongs = 2,
hook_pole = 2,
pick = 12,
saw = 9,
scythe = 4,
shovel = 9,
tabard = 5,
light_trident = 5,
},
workers = {
blackroot_farmer = 1,
builder = 10,
burner = 1,
carrier = 38,
fish_breeder = 1,
geologist = 4,
miner = 4,
stonecutter = 2,
toolsmith = 1,
woodcutter = 3,
horse = 5,
},
soldiers = {
[{0,0,0,0}] = 23,
},
})
_place_building_in_region(plr, "labyrinth", sf:region(11), {
wares = {
bread = 4,
smoked_fish = 3,
smoked_meat = 3,
}
})
_place_building_in_region(plr, "dungeon", sf:region(11), {
wares = {bread = 4, smoked_fish = 3, smoked_meat = 3}
})
_place_building_in_region(plr, "armoursmithy", sf:region(11), {
wares = { coal=4, gold =4 }
})
_place_building_in_region(plr, "toolsmithy", sf:region(11), {
wares = { trunk = 6 }
})
_place_building_in_region(plr, "weaponsmithy", sf:region(11), {
wares = { coal = 8, iron = 8 }
})
_place_building_in_region(plr, "sawmill", sf:region(11), {
wares = { trunk = 1 }
})
end) then
plr:send_message(_"Not enough space", _
[[Some of your starting buildings didn't have enough room and
weren't build. You are at an disadvantage with this; consider restarting
this map with a fair starting condition.]], {popup=true}
)
end
end
}
Edited:
2014-02-17, 23:22 UTC+1.0
Top
Quote
|
Adamant
Joined:
2012-10-11, 16:21 UTC+2.0
Posts: 180
Widelands-Forum-Junkie
Location: Alemania
|
Posted at:
2014-03-03, 09:12 UTC+1.0
I did not inspect fk's Code but want to add here some generic Informations about concerning Code Scope that I did for other Reasons reformat Code - concerns to Aim make it readable to me implies Application of own Indention Style (which sounds for other Programmers perhaps odd - I am sure, but I know that my Indention Style got confirmed enought from 3rd to know that it is not just my special Favor to rate it much better than conventional - just factor in that that Work is reasonable if know that indention style) while Reason was to learn how Lua works resp what it can do for Campaign starting with that Init-Scripts. As transformed both Scripts I did identify the Common resp found that HQ-Start is almost pure SubSet of CastleVillage-Start and did consider to combine both but got aware that something works wrong: Init-Scripts need different CFGs for Wares due to Build did not respect Build-Costs. I did not check precisely but Idea (est) was that CV-init did set Wares that lesser which it would consume when buld that Sites, it tries to set manuallly in Game. So Insufficience (it is not a Bug - Func to set without Build Costs is reasonable!!) is Func that triggers MaterialConsumption dependings from BuildCosts.
Would that exist, then CV-init could call the HQ-init-Script to set InitWares and Player wont have clearly DisAdvantages would that Init fail to set some Sites aside of Delay for building that Site manually.
The most significant Change I applied to Logic was that: (PSeudo-Code -- I am not experienced with Lua but can deal with sufficiently now in hours)
local wh; -- warehouse;
local hq; -- headquater
local port; -- guess
local store;
port=setSiteFunc(type=port ,args); store=port;
if not store then hq =setSiteFunc(type=headquater,args); store=hq; end;
if not store then wh =setSiteFunc(type=warehouse,args); store=wh; end;
if not store and not Plan_D then raise Fatal Err end
store.ware_type = val;
...
Soldier freshy = { } -- just defined -- remind Tutorial Campaign where such got used ... Point is reasonable named/preset Soldier-Types adding semantic to script
store.soldier = num * freshy; -- that Way like making also that Item looking mostly same like other store puts.
I did change something siginificant for Placement: I put the Stores Placement with same flexible Func like the other Sites which means that eg HQ does not get placed
exactly at given Player Position but in that Region. Due to unknown Reasons that simple Range Num Attribute did not perform like expected. Short Time later my Stuff
got deleted from new Installation and I felt somewhat disappointed.. btw: CNT for Lose of Work due to this or that got '4' .. I dont point to Causes here but Result was
I did resign on serious Work. Lost Work does represent as Sum about Work of 1/4 Year intensive Work ... that means avg 5 Day Week 8h Work at minimum... that
was Reason why I did decide to focus on Fun for 100% due to I did decide not to face Problems of arbitrary Nature and produce for Null Device..
So above were the most significant Changes resp Design-Decisions to change proofed Init-Scripts. I did indentify for BackUp ShipWreck and Proto-HQ of Barabarians
but did not identify a special Diff for Space-REQs that these appeared to represent reasonable Alternativs - plain said: If HQ and Port fails I wonder what can those do
better than WH and WH REQ medium Build-Space - the both listed Specials appeared unlikly to consume lesser and thus dont promise a Solution if the other fail.
I did intend to add them nevertheless not facrtoring in special Characteristics for healing/housing Troops -- now I would do for sure add them at any Level as Alternative
selected by Random to add that Way Diversity to Game: Player may wonder what Store they get each Time when multiple Types are at same Level. Before doing
that I tried to inspire to clear Issue of somebody can do ArtWork to give ALL Tribes same resp equivalent Meanings -ProtoHQ and Wreck .. another Question I did not
get FeedBack for. Do I blame for that? Do I? Do I? NO I dont! :) Other Reason was I did decide to ask for rnd() of Lua instead doing Research for by Trial and Error
etc resp wait till rnd run cross my Way .... Install did before.
That Thingy:
if not pcall(function()
_place_building_in_region(plr, "warehouse", sf:region(7), {
wares = {
diamond = 7,
ironore = 5,
I did transform Lua-Feature-unspecial to
_place_building_in_region(plr, "warehouse", sf:region(7) ;
_place_building_in_region(plr, "otherSiteTypes", sf:region(7);
...
and
warehouse.ware.diamond = 7;
warehouse.ware.ironore = 5;
due to I consider that as better readable and more important better editable.
Advantages for LVM not excluded but dunno how that Engine works. When
read its SRC Idea was that their Developers did not really had a stunning
Idea beyond adding Nil and bool Evaluation to all basic Types. Also allow
of additional trailing Comma I consider to be respectable but with Resign
for Parnthesis for logical Expression and Curly Brackets to define resp
delimit Scopes but instead use that end Symbol is really disgusting to
me and another Reason why I dont respect Lua as Solution but Draft for.
My Idea is Lua did success due to somebody wrote in Magenta easy at.
I forgot to note its Scope-Addressing, which I did invent as well and was
disappointed seeing Lua doing same similar -- I felt lesser special thus,
Point is I was really (.. means somewhat more) proud about and seeing
that in Lua let me feel that that is just ordinary and give it a lesser Rate
than before.. means I should here stress that Feature significant better.
But it did invent needless another stupid IndentionStyle which make it
impossible to calc analog x++; x-- ; no_nocomment="inc could get dealed but cmnt conflicts with dec..."
I saw often Code like x=x+1;
IIRC Lua can not do x++ but can do x+=1; btw
due to the comment issue I consider lua as (partial intentioal) stupid -- the end Notation fits into that Idea.
Alternative Eplanation is that that is due to is sooo easy. Lua gets written btw like Moon -- LUA is wrong!
Resign for Brackets factor perhaps in that Brackets are not simple. Luuuuuaaaa .. lua is wrong as well. (true Lua Fan)
Edited:
2014-03-03, 09:13 UTC+1.0
Ivan the Terrible is dead .. Genghis Khan is dead .. and I do not feel well, too.
Top
Quote
|