fortunes_foundation/ruleset.lua
2024-02-11 13:44:45 -08:00

198 lines
4.4 KiB
Lua

ruleset=klass()
function ruleset:init(
completion_level,
-- Number of unlocked slots (up to 11)
-- Includes the one in the middle
-- For Fortune's Foundation: 11
n_slots,
-- Number of suits (up to 5)
-- This is also the number of RHS wells
-- For Fortune's Foundation: 4
n_suits,
-- Number of cards per suit (up to 13)
-- For Fortune's Foundation: 13
n_cards_per_suit,
-- Number of arcana (unbounded)
-- For Fortune's Foundation: 22
n_arcana,
pool,
preferred_verse
)
self.completion_level=completion_level
self.n_slots=n_slots
self.n_suits=n_suits
self.n_cards_per_suit=n_cards_per_suit
self.n_arcana=n_arcana
self.pool=pool
self.preferred_verse=preferred_verse
assert(self.n_slots<=11)
assert(self.n_suits<=5)
assert(self.n_cards_per_suit<=13)
assert(self.n_arcana<=99)
-- the middle slot is always auxiliary in
-- Fortune's Foundation-style games
local usable_slots = n_slots - 1
assert(usable_slots%2==0)
local n_total_cards = n_arcana + n_suits * n_cards_per_suit
-- aces aren't usable because they are initially placed in the wells
local n_usable_cards = n_total_cards - self.n_suits
self.n_total_cards=n_total_cards
self.n_usable_cards=n_usable_cards
-- deal has to be symmetrical
assert(n_usable_cards % usable_slots == 0, usable_slots-(n_usable_cards%usable_slots))
-- these cards would be instantly moved to the wells and
-- therefore cannot be in the bottom row
local instantly_placed_cards = self.n_suits + 2
assert((n_total_cards-instantly_placed_cards)-usable_slots >= 0)
self:generate_deck()
self:generate_layouts()
end
function ruleset:generate_deck()
local ruleset=self
local possible_suits={"c","s","p","w","b"}
local deck={
aces={},
suits={},
cards={},
instantly_accepted={},
rank_name="a23456789tjqk"
}
self.deck=deck
for i=1,self.n_suits do
add(deck.suits,possible_suits[i])
end
-- suited cards
for suit in all(deck.suits) do
for rank=1,self.n_cards_per_suit do
add(deck.cards,{suit=suit,rank=rank})
if (rank==1) add(deck.aces,#deck.cards)
if (rank==2) deck.instantly_accepted[#deck.cards]=true
end
end
-- arcana
for rank=0,self.n_arcana-1 do
add(deck.cards,{suit="a",rank=rank})
if (rank==0 or rank==self.n_arcana-1) deck.instantly_accepted[#deck.cards]=true
end
function deck:draw_card(x,y,c,special)
if special.rotate then
camera(0,-64)
poke(0x5f55,0x00)
else
camera(-x,-y)
end
local meta=deck.cards[c]
local is_extreme=meta.rank==0 or meta.rank==ruleset.n_arcana-1
local s,fg
local bg
if meta.suit=='a' or meta.suit=='b' then
bg=1
if (is_extreme) bg=15
else
bg=7
end
if special.shadowed then
if (bg==1) bg=4
if (bg==7) bg=6
end
rectfill(0,0,8,15,bg)
if (meta.suit=='p') s,fg=0,4
if (meta.suit=='s') s,fg=1,12
if (meta.suit=='c') s,fg=2,2
if (meta.suit=='w') s,fg=3,3
if (meta.suit=='b') s,fg=4,14
if (meta.suit=='a') fg=15
if meta.suit=='a' then
local rank=""..meta.rank
pal(7,15)
if (is_extreme) pal(7,1)
print(meta.rank,5-#rank*2,1,7)
spr(5,0,8)
pal()
else
local name=sub(deck.rank_name,meta.rank,meta.rank)
local x2=0
if (meta.suit=='b') x2+=1
rectfill(0,0,3,6,fg)
print(name,x2,1,bg)
pal(7,fg)
spr(s,4,0)
spr(15+meta.rank,0,8)
pal()
end
camera()
if special.rotate then
poke(0x5f55,0x60)
mset(0,0,128)
mset(1,0,129)
mset(0,1,144)
mset(1,1,145)
x-=3
y+=7
for sx=0,8 do
for sy=0,15 do
tline(x+sy,y+sx,x+sy,y,(0)/8,sy/8,1/8,0)
end
end
tline()
end
return fg
end
end
function ruleset:generate_layouts()
local layouts={}
self.layouts=layouts
local ruleset=self
local width=ruleset.n_slots*10
local x=(128-width)\2
local y=9 -- 1 is also fine
function layouts:well(i)
if i<=ruleset.n_suits then
local wx=width-ruleset.n_suits*10+(i-1)*10
return layout:new(x+wx,y,layout_mode.obscured)
end
i-=ruleset.n_suits
if (i==1) return layout:new(x,y,layout_mode.obscured)
if (i==2) return layout:new(x+10,y,layout_mode.obscured)
if (i==3) return layout:new(x+5,y,layout_mode.rotated)
assert(false,"unknown well")
end
function layouts:checkpoint()
local wx=(ruleset.n_slots\2)*10
return layout:new(x+wx,y,layout_mode.obscured)
end
function layouts:slot(i)
if i<=ruleset.n_slots then
local sx=(i-1)*10
return layout:new(x+sx,y+17,layout_mode.vertical)
end
if (i==ruleset.n_slots+1) return layout:new(x+width-ruleset.n_suits*5-5,y,layout_mode.rotated)
assert(false, "unknown slot")
end
end