|
|
|
|
@@ -1,6 +1,6 @@
|
|
|
|
|
makeclass('player')
|
|
|
|
|
makeclass('army')
|
|
|
|
|
|
|
|
|
|
makeclass('orchard')
|
|
|
|
|
|
|
|
|
|
--
|
|
|
|
|
-- HORPS game: Walk around the board collecting armies and buffs
|
|
|
|
|
@@ -52,7 +52,8 @@ function army.interface(actor,place)
|
|
|
|
|
-- Spock vaporizes Rock 3
|
|
|
|
|
-- Spock dismantles Scissors 2
|
|
|
|
|
armytypes={'r','p','s'}
|
|
|
|
|
armynames={r="Rock Golem",p="Paper Dragon",s="Scissor Beast",l="Fire Lizzard",v="Mr. Spock"}
|
|
|
|
|
armynames={r="Rock Golem" ,p="Paper Dragon",s="Scissor Beast",l="Fire Lizzard",v="Mr. Spock"}
|
|
|
|
|
foodnames={r="Raspberry" ,p="Pomegranite" ,s="Strawberry" ,l="Lemon" ,v="Mango" }
|
|
|
|
|
--advantage={ r={ r=1, p=1/2, s=3, l=2, v=1/3 },
|
|
|
|
|
-- p={ r=2, p=1, s=1/2, l=1/3, v=3 },
|
|
|
|
|
-- s={ r=1/3, p=2, s=1, l=3, v=1/2 },
|
|
|
|
|
@@ -112,45 +113,61 @@ function MakeMap()
|
|
|
|
|
end end end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
--
|
|
|
|
|
-- For each creature type, select the optimal target. Select randomly among identical targets.
|
|
|
|
|
--
|
|
|
|
|
function army.fight0(ak,ac,dk,dc,rules) -- returns number of attacker casualties, defender casualties
|
|
|
|
|
if not rules then rules={} end
|
|
|
|
|
function army.fight0(ak,ac,dk,dc,tweekdefender) -- returns number of attacker casualties, defender casualties
|
|
|
|
|
local adv0=advantage[ak][dk]
|
|
|
|
|
local adv1=advantage[dk][ak]
|
|
|
|
|
if rules.counterattack=='one' then adv1=1
|
|
|
|
|
elseif rules.counterattack=='best' then adv1=adv1<1 and 1 or 1
|
|
|
|
|
end
|
|
|
|
|
local rval0=(ac*adv0-dc)/adv0
|
|
|
|
|
if rval0<0 then rval0=0 end
|
|
|
|
|
local rval1=(dc*adv1-rval0)/adv1
|
|
|
|
|
return rval0,rval1
|
|
|
|
|
if not tweekdefender then tweekdefender=function(adv) return adv end end
|
|
|
|
|
adv1=tweekdefender(adv1)
|
|
|
|
|
local losstotal=(ac+dc)/2
|
|
|
|
|
local power0=ac*adv0
|
|
|
|
|
local power1=dc*adv1
|
|
|
|
|
local powertotal=power0+power1
|
|
|
|
|
local loss0=math.min(ac,math.floor(losstotal*power1/powertotal))
|
|
|
|
|
local loss1=math.min(dc,math.floor(losstotal*power0/powertotal))
|
|
|
|
|
return loss0,loss1
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function player:fight(enemy)
|
|
|
|
|
local rval={}
|
|
|
|
|
for ak,ac in pairs(self.Count) do -- Should randomize the order
|
|
|
|
|
local enemyk, enemyc
|
|
|
|
|
local acas
|
|
|
|
|
local maxcas=-1
|
|
|
|
|
local Loss0,Loss1
|
|
|
|
|
local useloss0
|
|
|
|
|
local useloss1=-1
|
|
|
|
|
local loss0,loss1
|
|
|
|
|
local whichdk, whichdc
|
|
|
|
|
for dk,dc in pairs(enemy.Count) do
|
|
|
|
|
Loss0,Loss1=army.fight0(ak,ac,dk,dc)
|
|
|
|
|
print("When "..ac.." "..ak.." fight "..dc.." "..dk.." they kill "..Loss1.." and suffer "..Loss0)
|
|
|
|
|
if Loss1>maxcas then
|
|
|
|
|
loss0,loss1=army.fight0(ak,ac,dk,dc)
|
|
|
|
|
print("When "..ac.." "..ak.." fight "..dc.." "..dk.." they kill "..loss1.." and suffer "..loss0)
|
|
|
|
|
if loss1>useloss1 then
|
|
|
|
|
enemyk=dk
|
|
|
|
|
enemyc=dc
|
|
|
|
|
maxcas=Loss1
|
|
|
|
|
acas=Loss1
|
|
|
|
|
useloss1=loss1
|
|
|
|
|
useloss0=loss0
|
|
|
|
|
end end
|
|
|
|
|
if enemyk then
|
|
|
|
|
print("Army of "..ac.." "..ak.." fights "..enemyc.." "..enemyk..", killing "..Loss1.." and suffering "..Loss0)
|
|
|
|
|
print("Army of "..ac.." "..ak.." fights "..enemyc.." "..enemyk..", killing "..useloss1.." and suffering "..useloss0)
|
|
|
|
|
rval[1+#rval]={'fight',ak,ac,useloss0,enemyk,enemyc,useloss1}
|
|
|
|
|
enemy.Count[enemyk]=enemy.Count[enemyk]-useloss1
|
|
|
|
|
self.Count[ak]=self.Count[ak]-useloss0
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
local enemyleft=0
|
|
|
|
|
local playerleft=0
|
|
|
|
|
for dk,dc in pairs(enemy.Count) do enemyleft=enemyleft+dc end
|
|
|
|
|
for ak,ac in pairs(self.Count) do playerleft=playerleft+ac end
|
|
|
|
|
rval.enemyleft=enemyleft
|
|
|
|
|
return rval
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function player:cb_droprock(actor) player:droparmy(actor,'r') end
|
|
|
|
|
function player:cb_droppaper(actor) player:droparmy(actor,'p') end
|
|
|
|
|
function player:cb_dropscissor(actor) player:droparmy(actor,'s') end
|
|
|
|
|
@@ -165,9 +182,20 @@ function player:droparmy(actor,kind)
|
|
|
|
|
pprint(t)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function orchard:gather(actor)
|
|
|
|
|
actor.food[self.kind]=actor.inventory[self.kind]+self.count
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function player:newlocation()
|
|
|
|
|
local lis=tangible.near(self,0,true,true)
|
|
|
|
|
for _,t in ipairs(lis) do self:fight(t) end
|
|
|
|
|
local count={} setmetatable(count,NilIsZero)
|
|
|
|
|
local count0=0
|
|
|
|
|
local result={}
|
|
|
|
|
for _,t in ipairs(lis) do if tangible.getclass(t)=='army' then result[1+#result]=self:fight(t) end end
|
|
|
|
|
if #result==1 and result[1].enemyleft>0 then
|
|
|
|
|
for _,t in ipairs(lis) do if tangible.getclass(t)=='orchard' then t:gather(self) end end
|
|
|
|
|
end
|
|
|
|
|
return result
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function player:printanimstate()
|
|
|
|
|
@@ -175,28 +203,36 @@ function player:printanimstate()
|
|
|
|
|
print("Resulting state: ", graphic, plane, x, y, z, facing)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function player:walk(dx,dy)
|
|
|
|
|
tangible.animate(self,{action='walk',dx=dx,dy=dy})
|
|
|
|
|
local result=self:newlocation()
|
|
|
|
|
pprint(result)
|
|
|
|
|
if #result>1 then print("Error: multiple armies at one location")
|
|
|
|
|
elseif #result==1 then
|
|
|
|
|
if result[1].enemyleft>0 then tangible.animate(self,{action='walk',dx=-dx,dy=-dy}) end
|
|
|
|
|
end
|
|
|
|
|
-- self:cb_map()
|
|
|
|
|
if #result==1 then
|
|
|
|
|
for i,v in ipairs(result[1]) do
|
|
|
|
|
if v[1]=='fight' then print(v[3]..v[2].." attacks "..v[6]..v[5]..", killing "..v[7].." while losing "..v[4]) end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function player:cb_north()
|
|
|
|
|
tangible.animate(self, {action="walk", dy=1})
|
|
|
|
|
self:cb_map()
|
|
|
|
|
self:newlocation()
|
|
|
|
|
self:walk(0,1)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function player:cb_south()
|
|
|
|
|
tangible.animate(self, {action="walk", dy=-1})
|
|
|
|
|
self:cb_map()
|
|
|
|
|
self:newlocation()
|
|
|
|
|
self:walk(0,-1)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function player:cb_east()
|
|
|
|
|
tangible.animate(self, {action="walk", dx=1})
|
|
|
|
|
self:cb_map()
|
|
|
|
|
self:newlocation()
|
|
|
|
|
self:walk(1,0)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function player:cb_west()
|
|
|
|
|
tangible.animate(self, {action="walk", dx=-1})
|
|
|
|
|
self:cb_map()
|
|
|
|
|
self:newlocation()
|
|
|
|
|
self:walk(0,1)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -230,6 +266,7 @@ function player.cb_emit_buff(actor,place,dialog)
|
|
|
|
|
makeclass('army')
|
|
|
|
|
makeclass('buff')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function seq(a,b,c) return a<=b and b<=c or false end
|
|
|
|
|
function num2(a) if a<=9 then return " "..a else return a end end
|
|
|
|
|
|
|
|
|
|
|