diff --git a/luprex/core/lua/horps.lua b/luprex/core/lua/horps.lua index 51c09dc7..ca4274e3 100644 --- a/luprex/core/lua/horps.lua +++ b/luprex/core/lua/horps.lua @@ -1,70 +1,190 @@ makeclass('player') +makeclass('army') + +-- +-- HORPS game: Walk around the board collecting armies and buffs +-- Captured armies eat each turn +-- Attacking armies select order (random by default) +-- Defending armies are stronger +-- Command: Tame Creature Stack +-- Command: Free Creature Stack +-- -- -- Data Structure --- Army.Count --- Army.Kind 'r','p','s' +-- Army.Count[kind]=number Where kind is r,p,s -- function player.interface(actor, place) - gui.menu_item("cb_north", "Go North") - gui.menu_item("cb_south", "Go South") - gui.menu_item("cb_east", "Go East") - gui.menu_item("cb_west", "Go West") - gui.menu_item("cb_map", "Show the Map") - gui.menu_item("cb_emit_army","Emit an Army") - gui.menu_item("cb_emit_buff","Emit a Buff") -end + gui.menu_item("cb_north" ,"Go North") + gui.menu_item("cb_south" ,"Go South") + gui.menu_item("cb_east" ,"Go East") + gui.menu_item("cb_west" ,"Go West") + gui.menu_item("cb_map" ,"Show the Map") + gui.menu_item("cb_conjurerock" ,"Conjure Rock") + gui.menu_item("cb_conjurepaper" ,"Conjure Paper") + gui.menu_item("cb_conjurescissor" ,"Conjure Scissor") + gui.menu_item("cb_droprock" ,"Drop Rock") + gui.menu_item("cb_droppaper" ,"Drop Paper") + gui.menu_item("cb_dropscissor" ,"Drop Scissor") + end + +function player:cb_conjurerock() self.Count['r']=self.Count['r']+1 end +function player:cb_conjurepaper() self.Count['p']=self.Count['p']+1 end +function player:cb_conjurescissor() self.Count['s']=self.Count['s']+1 end + +function army.interface(actor,place) + if place.owner==actor then gui_menu_item("cb_recruit","Recruit"); + else gui.menu_item("cb_capture","Capture"); + end end + +-- Rock dulls Scissors 3 +-- Rock cripples Lizard 2 +-- Paper disproves Spock 3 +-- Paper covers Rock 2 +-- Scissors decapitates Lizard 3 +-- Scissors cuts Paper 2 +-- Lizard eats Paper 3 +-- Lizard poisons Spock 2 +-- 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"} +--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 }, +-- l={ r=1/2, p=3, s=1/3, l=1, v=2 }, +-- v={ r=3, p=1/3, s=2, l=1/2, v=1 } } +advantage={ r={ r=1, p=1/2, s=2 }, + p={ r=2, p=1, s=1/2 }, + s={ r=1/2, p=2, s=1 } } + +function shuffle(t) + local s={} + for i=1, #t do s[i]=t[i] end + for i=#t,2,-1 do + local j=math.random(i) + s[i],s[j]=s[j],s[i] + end + return s + end + + +-- +-- For each creature type, select the optimal target. Select randomly among identical targets. +-- +function army.fight0(ak,ac,dk,dc) -- returns number of attacker casualties, defender casualties + local adv0=advantage[ak][dk] + local adv1=advantage[dk][ak] + local rval0=(ac*adv0-dc)/adv0 + if rval0<0 then rval0=0 end + local rval1=(dc*adv1-rval0)/adv1 + return rval0,rval1 + end + +function army.cb_fight(actor,place,dialog) + for ak,ac in pairs(actor.Count) do -- Should randomize the order + local enemy + local acas + local maxcas=-1 + for dk,dc in pairs(place.Count) do + local rem0,rem1=army.fight0(ak,ac,dk,dc) + local Loss0=ac-rem0 + local Loss1=dk-rem1 + if Loss1>maxcas then + enemy=dk + maxcas=Loss1 + acas=Loss1 + end end + if enemy then + print("Army "..ak.." kills "..maxcas.." "..dk.." and suffers "..Loss0) + end + end + 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 + +function player:droparmy(actor,kind) + if actor.Count[kind]<=0 then print("No armies of typem "..kind.." available") return end + local lis=tangible.near(actor,0,true,true) + if #lis>1 then print("Multiple Tangibles Nearby") return end + local t=lis[1] + if t==nil then t=player:buildarmy(actor) end + t.Count[kind]=t.Count[kind]+1 + pprint(t) + end + +function player:newlocation() + local lis=tangible.near(self,0,false,false) + print("New Location") + pprint(lis) + end function player:printanimstate() - local graphic,plane,x,y,z,facing = tangible.animstate(self) - print("Resulting state: ", graphic, plane, x, y, z, facing) -end + local graphic,plane,x,y,z,facing = tangible.animstate(self) + print("Resulting state: ", graphic, plane, x, y, z, facing) + end -function player.cb_north(actor, place, dialog) - tangible.animate(place, {action="walk", dy=1}) - actor:printanimstate() -end +function player:cb_north() + tangible.animate(self, {action="walk", dy=1}) + self:newlocation() + end -function player.cb_south(actor, place, dialog) - tangible.animate(place, {action="walk", dy=-1}) - actor:printanimstate() -end +function player:cb_south(place, dialog) + tangible.animate(place, {action="walk", dy=-1}) + self:newlocation() + end function player.cb_east(actor, place, dialog) - tangible.animate(place, {action="walk", dx=1}) - actor:printanimstate() -end + tangible.animate(actor, {action="walk", dx=1}) + self:newlocation() + end + +function player:cb_west(actor, place, dialog) + tangible.animate(actor, {action="walk", dx=-1}) + self:newlocation() + end + + +function player:buildarmy(actor) + local _,pl,ax,ay=tangible.animstate(actor) + t={class='army',x=ax,y=ay,z=0,plane=pl,graphic='army'} + local nt=tangible.build(t) + nt.Count={} + setmetatable(nt.Count,{__index=function(t,k) return 0 end,__newindex=function(t,k,v) if v~=nil and v~=0 then rawset(t,k,v) end end}) + return nt + end -function player.cb_west(actor, place, dialog) - tangible.animate(place, {action="walk", dx=-1}) - actor:printanimstate() -end function player.cb_emit_army(actor,place,dialog) - local _,pl,ax,ay=tangible.animstate(actor) - t={class='army',x=ax,y=ay,z=0,plane=pl,graphic='army'} - pprint("building ",t) - tangible.build(t) - t.kind='r' - t.count=5 - end + local _,pl,ax,ay=tangible.animstate(actor) + t={class='army',x=ax,y=ay,z=0,plane=pl,graphic='army'} + pprint("building ",t) + local nt=tangible.build(t) + setmetatable(nt,{r=0,p=0,s=0}) + nt.kind='r' + nt.count=1 + end function player.cb_emit_buff(actor,place,dialog) - local _,pl,ax,ay=tangible.animstate(actor) - t={class='army',x=ax,y=ay,z=0,plane=pl,graphic='buff'} - pprint("building ",t) - tangible.build(t) - end + local _,pl,ax,ay=tangible.animstate(actor) + t={class='army',x=ax,y=ay,z=0,plane=pl,graphic='buff'} + pprint("building ",t) + tangible.build(t) + end 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 function player.cb_map(actor,place,dialog) local rad=2 - local scratch={} + scratch={} local lis=tangible.near(actor,rad,true,false) pprint("cb_map ",lis) for _,t in pairs(lis) do @@ -73,36 +193,43 @@ function player.cb_map(actor,place,dialog) local dx,dy=tangible.xyz(t) local offset=(dy+rad)*(rad*2+1)+dx+rad local cl=tangible.getclass(t) - print("Offset of "..cl.." is "..offset) + local kind=t.kind or 'Nil' + pprint(t) + print("Offset of "..cl.." is "..offset.." kind is "..kind) if not scratch[offset] then scratch[offset]={} end - if not scratch[offset].armies then scratch[offset].armies={} end - if cl=='player' then table.insert(scratch[offset].armies,t) end - if not scratch[offset].count then scratch[offset].count={} - if not scratch[offset].count[cl] then scratch[offset].count[cl]=0 end - if t.count then scratch[offset].count[cl]=scratch[offset].count[cl]+t.count end + if not scratch[offset].count then scratch[offset].count={} end + if not scratch[offset].count[kind] then scratch[offset].count[kind]=0 end + if t.count then scratch[offset].count[kind]=scratch[offset].count[kind]+t.count end end for dy=-rad,rad do for line=0,1 do local lbuf="" for dx=-rad,rad do - if line==0 then lbuf=lbuf.."---" + local offset=(dy+rad)*(rad*2+1)+dx+rad + if line==0 then lbuf=lbuf.."----" elseif line==1 then local kc=0 local tc=0 local kstr=' ' - for k,c in pairs(scratch[offset].count) do if c>0 then + if scratch[offset] then for k,c in pairs(scratch[offset].count) do if c>0 then kc=kc+1 tc=tc+c if kc>1 then kstr='M' else kstr=k end - end end - lbuf=lbuf.."-"..kstr..(tc>0 and tc or " ") + end end end + lbuf=lbuf.."-"..kstr..(tc>0 and num2(tc) or " ") end end lbuf=lbuf.."-" print(lbuf) end end - lbuf="" - for dx=-rad,rad do lbuf=lbuf.."---" end - lbuf=lbuf.."-" - print(lbuf) + lbuf="" + for dx=-rad,rad do lbuf=lbuf.."----" end + lbuf=lbuf.."-" + print(lbuf) + print("In Player:") + for k,v in pairs(actor.Count) do print(" "..k.." "..v) end + local lis=tangible.near(actor,0,true,true) + for k,v in pairs(lis) do + print("Army:") + for k2,v2 in pairs(v.Count) do print(" "..k2.." "..v2) end end end