ruleset=klass() function ruleset:init( -- 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 ) self.n_slots=n_slots self.n_suits=n_suits self.n_cards_per_suit=n_cards_per_suit self.n_arcana=n_arcana 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,shadow) local meta=deck.cards[c] local is_extreme=meta.rank==0 or meta.rank==ruleset.n_arcana-1 local s,fg local bg,shadowbg if meta.suit=='a' or meta.suit=='b' then bg,shadowbg=1,1 if (shadow) bg,shadowbg=1,1 if (is_extreme) bg,shadowbg=15,15 else bg,shadowbg=7,7 --if (shadow) bg,shadowbg=7,6 end rectfill(x,y,x+8,y+4,bg) rectfill(x,y+5,x+8,y+15,shadowbg) 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,x+5-#rank*2,y+1,7) spr(5,x,y+8) pal() else local name=sub(deck.rank_name,meta.rank,meta.rank) local x2=x if (meta.suit=='b') x2+=1 rectfill(x,y,x+3,y+6,fg) print(name,x2,y+1,bg) pal(7,fg) spr(s,x+4,y) if not shadow then spr(15+meta.rank,x,y+8) end pal() 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 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,1,layout_mode.obscured) end i-=ruleset.n_suits if (i==1) return layout:new(x,1,layout_mode.obscured) if (i==2) return layout:new(x+10,1,layout_mode.obscured) assert(false,"unknown well") end function layouts:slot(i) if i<=ruleset.n_slots then local sx=(i-1)*10 return layout:new(x+sx,18,layout_mode.vertical) end if (i==ruleset.n_slots+1) return layout:new(x+width-ruleset.n_suits*5-5,1,layout_mode.obscured) assert(false, "unknown slot") end end