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, pool ) 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 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) 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