Well, I'm going to mark this solved, I've figured out pretty well everything I wanted to do with the game!
Code: Select all
init:
default btn_selected = False
transform zoomy:
zoom 0.4
transform zoommid:
zoom 0.6
transform zoomnice:
zoom 0.69
transform zoomless:
zoom 0.7
screen santa_suit_selection:
hbox:
spacing 20
xalign 0.5
yalign 0.5
imagebutton:
idle "images/B0.png"
action Function(e.select_suit, 0)
imagebutton:
idle "images/B1.png"
action Function(e.select_suit, 1)
imagebutton:
idle "images/B2.png"
action Function(e.select_suit, 2)
imagebutton:
idle "images/B3.png"
action Function(e.select_suit, 3)
imagebutton:
idle "images/B4.png"
action Function(e.select_suit, 4)
screen grump_suit_selection:
hbox:
spacing 20
xalign 0.5
yalign 0.5
imagebutton:
idle "images/B0.png"
action Function(e.select_grump_suit, 0)
imagebutton:
idle "images/B1.png"
action Function(e.select_grump_suit, 1)
imagebutton:
idle "images/B2.png"
action Function(e.select_grump_suit, 2)
imagebutton:
idle "images/B3.png"
action Function(e.select_grump_suit, 3)
imagebutton:
idle "images/B4.png"
action Function(e.select_grump_suit, 4)
screen autotoggle:
hbox:
imagebutton:
idle "images/SwitchOff.png"
hover "images/SwitchOff.png"
selected_idle "images/SwitchOn.png"
selected_hover "images/SwitchOn.png"
action [ToggleVariable("e.auto_deal_mode", True, False)]
selected e.auto_deal_mode
xpos 1800 ypos 100
hbox:
text "Auto-Deal":
color "#FFFFFF"
size 12
xpos 1795 ypos 200
screen elfjack_interface:
vbox:
textbutton "Rules" action Show("rulebook1")
textbutton "Restart Game" action Function(e.restart_game)
textbutton "Undo Last Move" action Function(e.undo_drag)
textbutton "Change Setting" action ToggleVariable("e.current_location", 0, 1)
# textbutton "Change Card Back" action ToggleVariable("e.current_back", 0, 1, 2, 3, 4)
textbutton "Exit" action MainMenu(confirm=False)
screen background_table:
if e.current_location == 0:
add "images/bg/bg felt.png"
if e.current_location == 1:
add "images/bg/bg tabletop2.png"
screen winner:
vbox:
imagebutton:
idle "images/YouWin.png"
action MainMenu(confirm=False)
xpos 220 ypos 370
screen rulebook1:
vbox:
add "images/bg/bg darken.png"
vbox:
add "images/ElfjackOnlineRules.png"
xalign 0.5 yalign 0.33
vbox:
imagebutton:
idle "images/Right_idle.png"
hover "images/Right_Hover.png"
action [Show("rulebook2"), Hide("rulebook1")]
xpos 1700 ypos 780
at zoomy
vbox:
imagebutton:
idle "images/Exit.png"
action Hide("rulebook1")
xpos 900 ypos 930
at zoommid
screen rulebook2:
vbox:
add "images/bg/bg darken.png"
vbox:
add "images/ElfjackOnlineRules2.png"
xalign 0.5 yalign 0.33
vbox:
imagebutton:
idle "images/Left_Idle.png"
hover "images/Left_Hover.png"
action [Show("rulebook1"), Hide("rulebook2")]
xpos 40 ypos 780
at zoomy
vbox:
imagebutton:
idle "images/Exit.png"
action Hide("rulebook2")
xpos 900 ypos 930
at zoommid
label start:
scene bg transparency
show screen background_table onlayer bglayer
python:
e = ElfJack()
e.set_sensitive(True)
e.show()
# Show the autodeal toggle button
show screen autotoggle
show screen elfjack_interface
label continual:
while True:
python:
# ui.textbutton("Give Up", ui.jumps("giveup"), xalign=.02, yalign=.98)
# e.set_sensitive(True)
event = e.interact()
# e.update_table_images()
if event:
renpy.checkpoint()
if event == "win":
jump win
label win:
show screen winner
$ renpy.pause(hard=True)
return
Code: Select all
init python:
class ElfJack(object):
BAUBLE = 0
SNOW = 1
GINGER = 2
REINDEER = 3
STAR = 4
SANTA = 5
GRUMP = 6
CANE = 7
def __init__(self):
# Constants that let us easily change where the game is
# located.
LEFT=700
TOP=158
COL_SPACING = 150
ROW_SPACING = 180
CARD_XSPACING = 0.5
CARD_YSPACING = 0.5
# Create the table, stock, discard, and claim.
self.table = t = Table(base="images/base.png", back="images/back.png")
self.stock = t.stack(LEFT + 900, TOP, xoff=0.5, yoff=0.2, show=50, click=True)
self.claim = t.stack(LEFT + 950, TOP + 700, xoff=CARD_XSPACING, drag=DRAG_NONE, click=True)
self.hand = t.stack(LEFT + 105, TOP + 900, xoff=100, yoff=0, drag=DRAG_CARD, click=True)
self.current_location = 0
self.current_back = 0
self.last_card_event = None # Variable to store information about the last card event
self.auto_deal_mode = True
self.discard = []
d = t.stack(LEFT + 790, TOP + 700, xoff=CARD_XSPACING, yoff=CARD_YSPACING, show=50, drag=DRAG_NONE, click=True, drop=True)
self.discard.append(d)
# The 25 tableau stacks.
self.tableau = [ ]
for row in range(5):
for col in range(5):
s = t.stack(LEFT + COL_SPACING * col, TOP + ROW_SPACING * row, xoff=0, yoff=CARD_YSPACING, show=10, drag=DRAG_NONE, click=True, drop=True)
self.tableau.append(s)
# Create the stock and shuffle it.
for rank in range(0, 13):
for suit in range(0, 5):
value = (suit, rank)
t.card(value, "images/%d.png" % suit, back=None)
t.set_faceup(value, False)
self.stock.append(value)
self.stock.shuffle()
# Deal out the initial tableau.
for i in range(0, 1):
for j in range(0, 25):
c = self.stock.deal()
self.tableau[j].append(c)
self.table.set_faceup(c, True)
for rank in range(0, 3):
for suit in range(5, 7):
value = (suit, rank)
t.card(value, "images/%d.png" % suit)
t.set_faceup(value, False)
self.stock.append(value)
self.stock.shuffle()
for i in range(0, 5):
c = self.stock.deal()
self.hand.append(c)
self.table.set_faceup(c, True)
def show(self):
self.table.show()
def hide(self):
self.table.hide()
def restart_game(self):
# Reset necessary game state variables
self.tableau = []
self.discard = []
self.claim = []
self.hand = []
# Show the starting screen
renpy.jump("start")
def undo_drag(self):
# Check if there's a drag event in the last move
if self.last_card_event and self.last_card_event["type"] == "drag":
# Check if the 'drag_cards' key is present in the last card event
if "drag_cards" in self.last_card_event:
card = self.last_card_event["drag_cards"][0]
# Check if auto-deal mode is on
if self.auto_deal_mode:
# Return the auto-dealt card from the hand to the stock
auto_dealt_card = self.hand[-1] # Access the top card of the stack
self.table.set_faceup(auto_dealt_card, False)
self.stock.append(auto_dealt_card)
# Return the dragged card from the tableau or discard to the hand
self.hand.append(card) # Move the card to the hand
# Reset last_card_event
self.last_card_event = None
# def update_table_images(self):
# # Get the current state of your current_location variable
# current_location = self.current_location
# # Set the base and back images based on the current_location variable
# if current_location == 0: # Chateau
# # Change appearance for tableau stacks
# for stack in self.tableau:
# stack.base = "images/base.png"
# for card in stack:
# card.back = "images/back5.png"
# # Change appearance for other stacks
# for stack in [self.stock, self.discard, self.claim, self.hand]:
# stack.base = "images/base.png"
# for card in stack:
# card.back = "images/back5.png"
# elif current_location == 1: # Pub
# # Change appearance for tableau stacks
# for stack in self.tableau:
# stack.base = "images/base2.png"
# for card in stack:
# card.back = "images/back.png"
# # Change appearance for other stacks
# for stack in [self.stock, self.discard, self.claim, self.hand]:
# stack.base = "images/base2.png"
# for card in stack:
# card.back = "images/back.png"
def change_card_appearance(self, new_base, new_back):
# Change appearance for tableau stacks
for stack in self.tableau:
stack.base = new_base
for card in stack:
card.back = new_back
# Change appearance for other stacks
for stack in [self.stock, self.discard, self.claim, self.hand]:
stack.base = new_base
for card in stack:
card.back = new_back
def show_santa_suit_selection(self, tableau_stack):
renpy.call_screen("santa_suit_selection", tableau_stack)
def select_suit(self, button_index):
# Mapping button index to suit index
suit_index = button_index
# Iterate through all tableau stacks
for stack in self.tableau:
# Find Santa cards in the stack with the specified suit
santa_cards = [card for card in stack if card[0] == 5]
if santa_cards:
# Calculate the next rank based on the Santa card's index
next_rank = 13 + stack[-1][1]
# Update the suit and rank of any Santa cards in the tableau
for card in santa_cards:
value = (suit_index, next_rank)
self.table.card(value, "images/%d.png" % suit_index)
stack.remove(card) # Remove the old Santa card from the tableau
stack.append(value) # Add the updated card to the tableau
# After updating the Santa card, hide the santa_suit_selection screen
renpy.hide_screen("santa_suit_selection")
# You can return a value indicating the result, or None if not needed
return "suit_selected"
def toggle_auto_deal_mode(self):
# Toggle the auto-deal mode
self.auto_deal_mode = not self.auto_deal_mode
def show_grump_suit_selection(self, grump_stack):
renpy.call_screen("grump_suit_selection", grump_stack)
def select_grump_suit(self, button_index):
# Mapping button index to suit index
suit_index = button_index
# Get the index of the Grump stack
grump_stack_index = self.tableau.index([stack for stack in self.tableau if stack and stack[-1][0] == 6][0])
# Claim the Grump card
grump_stack = self.tableau[grump_stack_index]
grump_card = grump_stack[-1]
grump_stack.remove(grump_card)
self.claim.append(grump_card)
# Iterate through adjacent stacks of the chosen suit
for stack in self.tableau:
if stack and stack[-1][0] == suit_index and self.are_adjacent_stacks(grump_stack, stack):
card = stack.deal()
if card:
self.claim.append(card)
# After updating, hide the grump_suit_selection screen
renpy.hide_screen("grump_suit_selection")
return "grump_selected"
def are_adjacent_stacks(self, stack1, stack2):
# Check if two stacks are adjacent (orthogonal or diagonal)
row1, col1 = divmod(self.tableau.index(stack1), 5)
row2, col2 = divmod(self.tableau.index(stack2), 5)
return (
abs(row1 - row2) <= 1 and abs(col1 - col2) <= 1 and (row1 != row2 or col1 != col2)
)
def tableau_drag(self, evt):
# We can only drag one card at a time to a tableau space.
if len(evt.drag_cards) != 1:
return False
card = suit, rank = evt.drag_cards[0]
if card[0] == 5: # Check if it's a Santa card
evt.drop_stack.append(evt.drag_cards[0])
# Show suit selection buttons and pass the stack to select_suit
self.show_santa_suit_selection(evt.drop_stack)
return "tableau_drag" # Return after showing the suit selection buttons
if card[0] == 6: # Check if it's a Grump card
evt.drop_stack.append(evt.drag_cards[0])
# Show suit selection buttons and pass the stack to select_grump_suit
self.show_grump_suit_selection(evt.drop_stack)
return "tableau_drag" # Return after showing the suit selection buttons
evt.drop_stack.append(evt.drag_cards[0])
return "tableau_drag"
def discard_drag(self, evt):
card = suit, rank = evt.drag_cards[0]
evt.drop_stack.append(evt.drag_cards[0])
return "discard_drag"
def claim_drag(self, evt):
card = suit, rank = evt.drag_cards[0]
evt.drop_stack.append(evt.drag_cards[0])
return "claim drag"
def stock_click(self, evt):
if len(self.hand) == 5:
return False
else:
if self.stock:
c = self.stock.deal()
self.table.set_faceup(c, True)
self.hand.append(c)
def auto_deal_to_hand(self):
# Auto-deal cards from the stock to the hand until it reaches 5 cards
while len(self.hand) < 5 and self.stock:
c = self.stock.deal()
self.table.set_faceup(c, True)
self.hand.append(c)
def check_for_scoring(self):
row_suits = [[] for _ in range(5)] # Initialize lists for each row
col_suits = [[] for _ in range(5)] # Initialize lists for each column
for row in range(5):
for col in range(5):
stack = self.tableau[row * 5 + col] # Access the stack in the 5x5 grid
if stack and len(stack) > 0:
top_card = stack[-1]
suit = top_card[0] # Access the first element of the tuple
row_suits[row].append(suit)
col_suits[col].append(suit)
# Check for a run of five in rows
for row, suits in enumerate(row_suits, start=1):
if self.check_run_of_five(suits):
print(f"Five of a kind in Row {row}!")
self.move_cards_to_claim(row, 'row')
# Check for a run of five in columns
for col, suits in enumerate(col_suits, start=1):
if self.check_run_of_five(suits):
print(f"Five of a kind in Column {col}!")
self.move_cards_to_claim(col, 'col')
def check_run_of_five(self, suits):
# Check if there is a run of five of the same suit, including 0
for suit in set(suits):
if suits.count(suit) == 5:
return True
return False
def move_cards_to_claim(self, index, direction):
if direction == 'row':
for col_idx in range(5):
stack = self.tableau[(index - 1) * 5 + col_idx]
if stack:
card = stack.deal()
if card:
self.claim.append(card)
elif direction == 'col':
for row_idx in range(5):
stack = self.tableau[row_idx * 5 + index - 1]
if stack:
card = stack.deal()
if card:
self.claim.append(card)
return "claim_drag"
def interact(self):
evt = ui.interact()
rv = False
# Check the various events, and dispatch them to the methods
# that handle them.
if evt.type == "drag":
dragged_cards = getattr(evt, "drag_cards", []) # Get dragged cards if available
self.last_card_event = {"type": "drag", "data": evt, "stack": evt.drop_stack, "drag_cards": dragged_cards}
if evt.drop_stack in self.tableau:
rv = self.tableau_drag(evt)
elif evt.drop_stack in self.discard:
rv = self.discard_drag(evt)
elif evt.drop_stack in self.claim:
rv = self.claim_drag(evt)
elif evt.type == "click":
if evt.stack == self.stock:
rv = self.stock_click(evt)
# Save game state after each interaction
renpy.checkpoint()
# Print the content of self.last_card_event
print(f"self.last_card_event: {self.last_card_event}")
if self.auto_deal_mode == True:
self.auto_deal_to_hand()
self.check_for_scoring()
self.check_for_scoring()
if self.auto_deal_mode == True:
self.auto_deal_to_hand()
# Check for the win condition when all tableau stacks are empty.
if all(len(stack) == 0 for stack in self.tableau):
return "win"
return rv
# Sets things as sensitive (or not).
def set_sensitive(self, value):
self.table.set_sensitive(value)
The only thing I couldn't figure out in the end was how to dynamically change the base and back images used for the table... I wanted them to change along with the setting change, but kept getting errors. If anybody has any suggestions for how to implement that, I'd be very grateful! And if I ever figure it out, I'll post an update.