Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Shhhhh... it's (yet another) Solitaire
#11
I've installed a rudimentary "solve" button that becomes available when all cards are face up, though ideally the waste pile should either be cleared or in some semblance of numerical order before using it. I'm going to do some head scratching on an animation for that function. You can also {s}ave a hand in progress and {l}oad it later.

Code: (Select All)
OPTION _EXPLICIT
$COLOR:32
_TITLE "Quiet Solitaire"

TYPE V2 '                                                       Position (x, y)     Vector <x, y> pair
    x AS INTEGER
    y AS INTEGER
END TYPE

TYPE region
    ul AS V2 '                                                  upper left position
    lr AS V2 '                                                  lower right position
END TYPE

TYPE card
    in AS INTEGER '                                             index of card
    rk AS INTEGER '                                             rank of card (A,2,3,4,5,6,7,8,9,10,J,Q,K)  sequential from 1 to 13
    st AS INTEGER '                                             suit of card (2-5)  black even, red odd
    im AS LONG '                                                image handle of card
    fc AS _BYTE '                                               facing of card (up=true, down=false)
END TYPE

DIM SHARED Main&
Main& = _NEWIMAGE(680, 540, 32)

SCREEN Main&

DO: LOOP UNTIL _SCREENEXISTS
_SCREENMOVE 5, 5

DIM SHARED Mouse_StartX, Mouse_StartY, Mouse_EndX, Mouse_EndY
DIM AS INTEGER tog
tog = 0

DIM SHARED deck(52) AS card '                                   The Deck
DIM SHARED transfer AS INTEGER '                                stack movement flag
DIM SHARED fromPile AS INTEGER '                                stack moved from
REDIM SHARED pick%(13) '                                        moving array

'card stacks
DIM SHARED stack(12, 52) AS INTEGER '      first dimenstion=stack pointer  second dimension=index array
'stack 0 = draw pile                                              "Stock"
'stack 1 = drawn pile                                             "Waste"
'stacks 2-5 = ace pile     clubs - hearts - spades - diamonds     "foundation"
DIM SHARED suitname$(2 TO 5)
suitname$(2) = "Clubs"
suitname$(3) = "Hearts"
suitname$(4) = "Spades"
suitname$(5) = "Diamonds"
'stacks 6-12 =  7 build piles                                     "Tableau"

$EMBED:'./Cards.png','Carddeck'

DIM CardDeck&
CardDeck& = _LOADIMAGE(_EMBEDDED$("Carddeck"), 32, "memory")
IF CardDeck& = -1 THEN PRINT "Cards.png failed to load, bye!": END

DIM rank%, suit%
DIM AS INTEGER SW, SH, SPRow, SPCol, Peektop
rank% = 1: suit% = 1
SW = 72: SH = 96: SPRow = 13: SPCol = 4: Peektop = 18


CONST back = 10 '                                               display offset for face down cards in build stacks
CONST face = 24 '                                               display offset for face up cards in build stacks
CONST TRUE = -1
CONST FALSE = 0

' cards 72 x 96   3x4

deck(0).im = _NEWIMAGE(72, 96, 32) '                            create card back image
_PUTIMAGE , CardDeck&, deck(0).im, (13 * SW, 0 * SH)-STEP(SW, SH) 'put card back sprite in image handle

'original sprite order: clubs spades hearts diamonds    swap spades and hearts to align even/odd suit numbering to red/black
DIM x%, sheetx%, sheety%
suit% = 2
FOR x% = 1 TO 52
    deck(x%).in = x%
    deck(x%).rk = rank%
    deck(x%).st = suit% '
    deck(x%).im = _NEWIMAGE(72, 96, 32)
    deck(x%).fc = 0
    sheetx% = ((x% - 1) MOD SPRow) * SW
    SELECT CASE x%
        CASE 1 TO 13 '                                Clubs               suit=1
            sheety% = 0 '
        CASE 14 TO 26 '                               Spades to Hearts    suit=2
            sheety% = 2 * SH
        CASE 27 TO 39 '                               Hearts to Spades    suit=3
            sheety% = SH
        CASE 40 TO 52 '                               Diamonds            suit=4
            sheety% = 3 * SH
    END SELECT
    _PUTIMAGE , CardDeck&, deck(x%).im, (sheetx%, sheety%)-STEP(SW, SH)
    rank% = rank% + 1 '                                         Ace to King ascending
    IF x% MOD 13 = 0 THEN
        suit% = suit% + 1
        rank% = 1
    END IF
NEXT x%

'PLAY LAYOUT REGIONS
DIM mp AS V2
DIM SHARED tpstk(12) AS region
DIM SHARED sbut AS region
'Set_Stacks scrw%, scrh%
DIM xset%, yset%
xset% = 10: yset% = 10
tpstk(0).ul.x = xset%: tpstk(0).ul.y = yset%: tpstk(0).lr.x = SW + xset%: tpstk(0).lr.y = SH + yset% 'draw stack
xset% = xset% + 10 + SW
tpstk(1).ul.x = xset%: tpstk(1).ul.y = yset%: tpstk(1).lr.x = SW + xset%: tpstk(1).lr.y = SH + yset% 'discard stack
xset% = xset% + 3 * SW
tpstk(2).ul.x = xset%: tpstk(2).ul.y = yset%: tpstk(2).lr.x = SW + xset%: tpstk(2).lr.y = SH + yset% 'clubs stack
xset% = xset% + 10 + SW
tpstk(3).ul.x = xset%: tpstk(3).ul.y = yset%: tpstk(3).lr.x = SW + xset%: tpstk(3).lr.y = SH + yset% 'hearts stack
xset% = xset% + 10 + SW
tpstk(4).ul.x = xset%: tpstk(4).ul.y = yset%: tpstk(4).lr.x = SW + xset%: tpstk(4).lr.y = SH + yset% 'spades stack
xset% = xset% + 10 + SW
tpstk(5).ul.x = xset%: tpstk(5).ul.y = yset%: tpstk(5).lr.x = SW + xset%: tpstk(5).lr.y = SH + yset% 'diamonds stack
xset% = 10: yset% = yset% + SH + 50
tpstk(6).ul.x = xset%: tpstk(6).ul.y = yset%: tpstk(6).lr.x = xset% + SW: tpstk(6).lr.y = _HEIGHT - 1 'build 1 stack
xset% = xset% + 20 + SW
tpstk(7).ul.x = xset%: tpstk(7).ul.y = yset%: tpstk(7).lr.x = xset% + SW: tpstk(7).lr.y = _HEIGHT - 1 'build 2 stack
xset% = xset% + 20 + SW
tpstk(8).ul.x = xset%: tpstk(8).ul.y = yset%: tpstk(8).lr.x = xset% + SW: tpstk(8).lr.y = _HEIGHT - 1 'build 3 stack
xset% = xset% + 20 + SW
tpstk(9).ul.x = xset%: tpstk(9).ul.y = yset%: tpstk(9).lr.x = xset% + SW: tpstk(9).lr.y = _HEIGHT - 1 'build 4 stack
xset% = xset% + 20 + SW
tpstk(10).ul.x = xset%: tpstk(10).ul.y = yset%: tpstk(10).lr.x = xset% + SW: tpstk(10).lr.y = _HEIGHT - 1 'build 5 stack
xset% = xset% + 20 + SW
tpstk(11).ul.x = xset%: tpstk(11).ul.y = yset%: tpstk(11).lr.x = xset% + SW: tpstk(11).lr.y = _HEIGHT - 1 'build 6 stack
xset% = xset% + 20 + SW
tpstk(12).ul.x = xset%: tpstk(12).ul.y = yset%: tpstk(12).lr.x = xset% + SW: tpstk(12).lr.y = _HEIGHT - 1 'build 7 stack

sbut.ul.x = SW * 2 + 30: sbut.ul.y = 10: sbut.lr.x = sbut.ul.x + SW: sbut.lr.y = sbut.ul.y + (SH \ 4)

DIM SHARED A(52) AS INTEGER
FOR x% = 1 TO 52: A(x%) = x%: NEXT x%

Initialize
Card_Refresh
DIM dn%, k$, in%, ms
dn% = 0
DO
    DO
        k$ = INKEY$
        IF k$ = CHR$(27) THEN in% = -1: dn% = -1
        IF k$ = CHR$(116) THEN tog = NOT tog: in% = -1 'Cheating Easter egg
        IF k$ = CHR$(108) THEN 'load
            Load_Hand
            Card_Refresh
        END IF
        IF k$ = CHR$(115) THEN 'save
            Save_Hand
        END IF
        IF k$ = CHR$(100) THEN
            Initialize
            in% = -1
        END IF
        ms = MBS%
        mp.x = _MOUSEX: mp.y = _MOUSEY
        IF ms AND 1 THEN
            Clear_MB 1
            'Mouse_LeftII mp
            Mouse_Left mp
            in% = -1
        END IF
        IF ms AND 2 THEN
            Clear_MB 2
            Mouse_Right mp
            in% = -1
        END IF
        _LIMIT 30
    LOOP UNTIL in%
    in% = 0
    IF tog THEN
        Card_List
    ELSE
        Card_Refresh
    END IF
    'IF UpCheck% THEN
    '    'all cards up, put up a solve button
    'END IF
    IF Victory_Check% THEN
        _PRINTSTRING (_WIDTH / 2 - 32, _HEIGHT / 2), "Winner!"
    END IF
    _DISPLAY
LOOP UNTIL dn%

END


'---------------------------------------------------------------
SUB Analyze_Stack (down AS INTEGER, up AS INTEGER, index AS INTEGER)
    DIM x%
    down = 0
    up = 0
    x% = 0
    DO UNTIL stack(index, x%) = 0
        SELECT CASE deck(stack(index, x%)).fc
            CASE TRUE: up = up + 1 '                            count face up
            CASE FALSE: down = down + 1 '                       count face down
        END SELECT
        x% = x% + 1
    LOOP
END SUB 'Analyze_Stack

'---------------------------------------------------------------
SUB Box_Region (b AS region, c AS LONG, t AS INTEGER)
    DIM x%
    FOR x% = 0 TO t - 1
        LINE (b.ul.x + x%, b.ul.y + x%)-(b.lr.x - x%, b.lr.y - x%), c, B
    NEXT x%
END SUB 'Box_Region

'---------------------------------------------------------------debugging and cheating Easter egg
SUB Card_List
    DIM bld%, ace%, dn%, up%, y%, r%, num$, suit$
    DIM AS INTEGER ypos
    CLS
    FOR ace% = 2 TO 5
        ypos = 0: r% = 0
        Box_Region tpstk(ace%), Red, 1
        Analyze_Stack dn%, up%, ace%
        IF up% > 0 THEN
            FOR y% = 1 TO up%
                num$ = Rank_Name$(deck(stack(ace%, r%)))
                suit$ = Suit_Name$(deck(stack(ace%, r%)))
                _PRINTSTRING (tpstk(ace%).ul.x, ypos), LEFT$(num$, 4) + LEFT$(suit$, 4)
                ypos = ypos + 16 '                            increment ypos by back constant
                r% = r% + 1
            NEXT y%
        END IF
    NEXT ace%
    FOR bld% = 6 TO 12
        r% = 0
        ypos = tpstk(bld%).ul.y
        Box_Region tpstk(bld%), &HFFFF0000, 1
        Analyze_Stack dn%, up%, bld%
        'place any face down cards
        IF dn% > 0 THEN
            FOR y% = 1 TO dn%
                COLOR &HFFFF0000
                num$ = Rank_Name$(deck(stack(bld%, r%)))
                suit$ = Suit_Name$(deck(stack(bld%, r%)))
                _PRINTSTRING (tpstk(bld%).ul.x, ypos), LEFT$(num$, 4) + LEFT$(suit$, 4)
                ypos = ypos + 16 '                            increment ypos by back constant
                r% = r% + 1
            NEXT y%
        END IF
        'place any face up cards
        IF up% > 0 THEN
            FOR y% = 1 TO up%
                COLOR &HFFFFFFFF
                num$ = Rank_Name$(deck(stack(bld%, r%)))
                suit$ = Suit_Name$(deck(stack(bld%, r%)))
                _PRINTSTRING (tpstk(bld%).ul.x, ypos), LEFT$(num$, 4) + LEFT$(suit$, 4)
                ypos = ypos + 16 '                            increment ypos by face constant
                r% = r% + 1
            NEXT y%
        END IF
    NEXT bld%
    Box_Region tpstk(0), &HFFFF0000, 1
    Analyze_Stack dn%, up%, 0
    FOR y% = 0 TO dn% - 1
        _PRINTSTRING (5, _HEIGHT - (20 + y% * 16)), Rank_Name$(deck(stack(0, y%))) + " of " + Suit_Name$(deck(stack(0, y%)))
    NEXT y%
    Analyze_Stack dn%, up%, 1
    FOR y% = 0 TO up% - 1
        _PRINTSTRING (200, _HEIGHT - (20 + y% * 16)), Rank_Name$(deck(stack(1, y%))) + " of " + Suit_Name$(deck(stack(1, y%)))
    NEXT y%
END SUB 'Card_List

'---------------------------------------------------------------
SUB Card_Refresh
    DIM AS INTEGER ypos
    DIM x%, y%, r%, trash%, ace%, bld%, up%, dn%
    DIM img&, mc&, q&, px&
    DIM AS V2 mid
    DIM m AS _MEM
    CLS , Green
    IF UpCheck% THEN
        'set a flag to reveal the solve button
        Box_Region sbut, Red, 3
        Mid_Region mid, sbut
        _PRINTSTRING (mid.x - 20, mid.y - 8), "Solve"
    END IF
    IF stack(0, 0) <> 0 THEN '..................................Stock Stack
        trash% = Image_Region(tpstk(0), deck(0).im, Main&, "c", "c")
    ELSE
        Box_Region tpstk(0), &HFFFF0000, 1
    END IF
    IF stack(1, 0) <> 0 THEN '..................................Waste Stack
        x% = 0
        DO UNTIL stack(1, x% + 1) = 0
            x% = x% + 1
        LOOP
        'Analyze_Stack dn%, up%, 1
        IF transfer AND fromPile = 1 THEN
            'negative
            img& = _COPYIMAGE(deck(stack(1, x%)).im)
            m = _MEMIMAGE(img&)
            mc& = 0
            DO
                _MEMGET m, m.OFFSET + mc& * 4, px&
                q& = Negative&(px&)
                _MEMPUT m, m.OFFSET + mc& * 4, q&
                mc& = mc& + 1
            LOOP UNTIL mc& * 4 = m.SIZE - 4
            _PUTIMAGE (tpstk(1).ul.x, tpstk(1).ul.y), img&
            _MEMFREE m
        ELSE
            trash% = Image_Region(tpstk(1), deck(stack(1, x%)).im, Main&, "c", "c")
        END IF
    ELSE
        Box_Region tpstk(1), &HFFFF0000, 1
    END IF
    'STACK 2 - 5
    FOR ace% = 2 TO 5 '.........................................Foundation Stacks
        IF stack(ace%, 0) <> 0 THEN
            'show the topmost
            Analyze_Stack dn%, up%, ace%
            IF up% + dn% > 0 THEN
                trash% = Image_Region(tpstk(ace%), deck(stack(ace%, up% + dn% - 1)).im, Main&, "c", "c")
            END IF
        ELSE
            DIM tc AS V2
            Box_Region tpstk(ace%), &HFFFF0000, 1
            Mid_Region tc, tpstk(ace%)
            _PRINTSTRING (tc.x - _SHL(LEN(suitname$(ace%)), 2), tc.y - 8), suitname$(ace%)
        END IF
    NEXT ace%
    FOR bld% = 6 TO 12 '........................................Tableau Stacks
        r% = 0
        ypos = tpstk(bld%).ul.y
        Analyze_Stack dn%, up%, bld%
        'place any face down cards
        IF dn% > 0 THEN
            FOR y% = 1 TO dn%
                _PUTIMAGE (tpstk(bld%).ul.x, ypos), deck(0).im 'place card back
                ypos = ypos + back '                            increment ypos by back constant
                r% = r% + 1
            NEXT y%
        END IF
        'place any face up cards
        IF up% > 0 THEN
            FOR y% = 1 TO up%
                _PUTIMAGE (tpstk(bld%).ul.x, ypos), deck(stack(bld%, r%)).im 'place card face
                IF transfer AND bld% = fromPile THEN
                    img& = _COPYIMAGE(deck(stack(bld%, r%)).im)
                    m = _MEMIMAGE(img&)
                    mc& = 0
                    DO
                        _MEMGET m, m.OFFSET + mc& * 4, px&
                        q& = Negative&(px&)
                        _MEMPUT m, m.OFFSET + mc& * 4, q&
                        mc& = mc& + 1
                    LOOP UNTIL mc& * 4 = m.SIZE - 4
                    _PUTIMAGE (tpstk(bld%).ul.x, ypos), img&
                    _MEMFREE m
                END IF
                ypos = ypos + face '                            increment ypos by face constant
                r% = r% + 1
            NEXT y%
        END IF
    NEXT bld%
    _PRINTMODE _KEEPBACKGROUND
    _PRINTSTRING (5, _HEIGHT - 17), "d = deal   l = load   s = save   esc = quit"
END SUB 'Card_Refresh

'---------------------------------------------------------------
'Description
'Clear the mousebutton queue - only releases when button released
SUB Clear_MB (var AS INTEGER)
    DO UNTIL NOT _MOUSEBUTTON(var)
        _LIMIT 30
        WHILE _MOUSEINPUT: WEND
    LOOP
END SUB 'Clear_MB

'---------------------------------------------------------------
SUB Deal
    DIM x%, r%, dr%, st%
    DO
        FOR st% = 6 TO 12
            IF st% - 6 - r% < 0 THEN
                stack(st%, r%) = 0 '                            put a zero where no card on the deal
            ELSE
                x% = x% + 1 '                                   index for next card
                stack(st%, r%) = A(x%) '                        place card x% on stack st% and rank r%
                deck(A(x%)).fc = _IIF(st% - 6 - r% = 0, -1, 0) 'face up first card of the stack rank
            END IF
        NEXT st%
        r% = r% + 1
    LOOP UNTIL r% = 7
    DO '                                                        put the rest in the draw
        x% = x% + 1
        deck(A(x%)).fc = 0
        stack(0, dr%) = A(x%)
        dr% = dr% + 1
    LOOP UNTIL x% = 52
    DO
        stack(0, dr%) = 0
        dr% = dr% + 1
    LOOP UNTIL dr% = 53
    transfer = 0
END SUB 'Deal

'---------------------------------------------------------------
FUNCTION Go% (from AS INTEGER, tto AS INTEGER)
    IF deck(from).rk = deck(tto).rk - 1 THEN '                  if from card is one less than to card
        IF deck(from).st MOD 2 <> deck(tto).st MOD 2 THEN '     if suit color alternates
            Go% = TRUE
        ELSE
            Go% = FALSE
        END IF
    ELSE
        Go% = FALSE
    END IF
END FUNCTION 'Go%

'---------------------------------------------------------------
FUNCTION Image_Region (r AS region, i AS LONG, d AS LONG, xj AS STRING, yj AS STRING)
    DIM AS INTEGER xs, ys, xp, yp, xl, yl '                     ready for OPTION EXPLICIT programs
    xp = r.ul.x: yp = r.ul.y: xl = r.lr.x: yl = r.lr.y '        isolate sent parameters from any changes
    DIM AS SINGLE rt, xrt, yrt
    xrt = (xl - xp) / _WIDTH(i) '                               width of area divided by width of image
    yrt = (yl - yp) / _HEIGHT(i) '                              height of area divided by height of image
    rt = _IIF(xrt < yrt, xrt, yrt) '                            pick the smaller of the two ratios to fit area
    xs = _WIDTH(i) * rt '                                       final image size ratio in x
    ys = _HEIGHT(i) * rt '                                      final image size ratio in y
    xp = -xp * (xj = "l") - (_SHR(xl - xp, 1) + xp - _SHR(xs, 1)) * (xj = "c") - (xl - xs) * (xj = "r")
    xl = xp + xs
    yp = -yp * (yj = "u") - (_SHR(yl - yp, 1) + yp - _SHR(ys, 1)) * (yj = "c") - (yl - ys) * (yj = "d")
    yl = yp + ys
    _PUTIMAGE (xp, yp)-(xl, yl), i, d
    Image_Region = rt
END FUNCTION 'Image_Region

'---------------------------------------------------------------
SUB Initialize
    DIM st%, sl%
    FOR st% = 0 TO 12
        FOR sl% = 0 TO 52
            stack(st%, sl%) = 0
        NEXT sl%
    NEXT st%
    Shuffle A()
    Deal
END SUB 'Initialize

'---------------------------------------------------------------
FUNCTION InRange% (var##, ll##, ul##)
    InRange% = _CLAMP(var##, ll##, ul##) = var##
END FUNCTION 'InRange4%

'---------------------------------------------------------------
FUNCTION InRegion% (p AS V2, r AS region)
    InRegion% = -(InRange%(p.x, r.ul.x, r.lr.x) * InRange%(p.y, r.ul.y, r.lr.y)) 'in region? T/F
END FUNCTION 'InRegion%

'---------------------------------------------------------------
' Description:
' Polls state of mouse wheel and buttons and allows drag operations.
' Author: Steve McNeill
FUNCTION MBS% 'Mouse Button Status
    DIM AS INTEGER tempMBS, BD
    STATIC StartTimer AS _FLOAT
    STATIC ButtonDown AS INTEGER
    STATIC ClickCount AS INTEGER
    CONST ClickLimit## = 0.2 'Less than 1/4th of a second to down, up a key to count as a CLICK.
    '                          Down longer counts as a HOLD event.
    SHARED Mouse_StartX, Mouse_StartY, Mouse_EndX, Mouse_EndY
    WHILE _MOUSEINPUT 'Remark out this block, if mouse main input/clear is going to be handled manually in main program.
        SELECT CASE SGN(_MOUSEWHEEL)
            CASE 1: tempMBS = tempMBS OR 512
            CASE -1: tempMBS = tempMBS OR 1024
        END SELECT
    WEND
    IF _MOUSEBUTTON(1) THEN tempMBS = tempMBS OR 1
    IF _MOUSEBUTTON(2) THEN tempMBS = tempMBS OR 2
    IF _MOUSEBUTTON(3) THEN tempMBS = tempMBS OR 4
    IF StartTimer = 0 THEN
        IF _MOUSEBUTTON(1) THEN 'If a button is pressed, start the timer to see what it does (click or hold)
            ButtonDown = 1: StartTimer = TIMER(0.01)
            Mouse_StartX = _MOUSEX: Mouse_StartY = _MOUSEY
        ELSEIF _MOUSEBUTTON(2) THEN
            ButtonDown = 2: StartTimer = TIMER(0.01)
            Mouse_StartX = _MOUSEX: Mouse_StartY = _MOUSEY
        ELSEIF _MOUSEBUTTON(3) THEN
            ButtonDown = 3: StartTimer = TIMER(0.01)
            Mouse_StartX = _MOUSEX: Mouse_StartY = _MOUSEY
        END IF
    ELSE
        BD = ButtonDown MOD 3
        IF BD = 0 THEN BD = 3
        IF TIMER(0.01) - StartTimer <= ClickLimit THEN 'Button was down, then up, within time limit.  It's a click
            IF _MOUSEBUTTON(BD) = 0 THEN tempMBS = 4 * 2 ^ ButtonDown: ButtonDown = 0: StartTimer = 0
        ELSE
            IF _MOUSEBUTTON(BD) = 0 THEN 'hold event has now ended
                tempMBS = 0: ButtonDown = 0: StartTimer = 0
                Mouse_EndX = _MOUSEX: Mouse_EndY = _MOUSEY
            ELSE 'We've now started the hold event
                tempMBS = tempMBS OR 32 * 2 ^ ButtonDown
            END IF
        END IF
    END IF
    MBS% = tempMBS
END FUNCTION 'MBS%

'---------------------------------------------------------------
SUB Mid_Region (re AS V2, send AS region)
    '            ³          ÀÄ region sent to find mid point of
    '            ÀÄ (x, y) point returned
    re.x = _SHR(send.lr.x - send.ul.x, 1) + send.ul.x
    re.y = _SHR(send.lr.y - send.ul.y, 1) + send.ul.y
END SUB 'Mid_Region

'---------------------------------------------------------------
SUB Mouse_Left (ms AS V2)
    DIM x%, a%, t%, d%, u%, df%, uf%, i%, ran%, m%, f%, flg%
    FOR x% = 0 TO 12
        IF InRegion(ms, tpstk(x%)) THEN EXIT FOR
    NEXT x%
    SELECT CASE x%
        CASE 0 '                                                STOCK STACK REGION
            IF transfer THEN transfer = NOT transfer
            IF stack(0, 0) = 0 THEN '                           reset from waste stack back to stock stack when empty
                Analyze_Stack d%, u%, 1
                RANDOMIZE TIMER
                FOR m% = 0 TO d% + u% - 1
                    ran% = INT(RND * (d% + u%))
                    SWAP stack(1, m%), stack(1, ran%)
                NEXT m%
                DO
                    Push Pop(1), 0, -1
                LOOP UNTIL stack(1, 0) = 0
            ELSE '                                              draw card from stock stack and place on top of waste stack
                Push Pop(0), 1, -1
            END IF
        CASE 1 '                                                WASTE STACK REGION
            transfer = NOT transfer
            fromPile = x%
        CASE 2 TO 5 '                                           FOUNDATION STACK REGIONS
        CASE 6 TO 12 '                                          TABLEAU STACK REGIONS
            Analyze_Stack d%, u%, x% '
            transfer = NOT transfer
            IF u% <> 0 THEN '                                   if face up cards are present in the stack
                IF transfer THEN '                              Are we in a potential transfer move?
                    fromPile = x% '                             Yes. Assign fromPile, but do nothing until the next column click
                ELSE '                                          No. Complete the transfer from the previously chosen fromPile
                    IF x% = fromPile THEN
                        fromPile = 0
                    ELSE
                        Analyze_Stack df%, uf%, fromPile
                        IF fromPile = 1 THEN
                            IF Go%(stack(1, df% + uf% - 1), stack(x%, d% + u% - 1)) THEN
                                Push Pop(1), x%, 0
                            END IF
                            EXIT SUB '                          a simple waste to tableau, one card transfer. Our job is done here.
                        END IF
                        GOSUB grab_face_ups
                        FOR t% = 0 TO UBOUND(pick%)
                            IF Go%(pick%(t%), stack(x%, d% + u% - 1 + i%)) THEN 'does pick card go on top tableau card?
                                i% = i% + 1
                                stack(x%, d% + u% - 1 + i%) = pick%(t%) 'Yes increment counter i% and transfer the element
                            END IF
                        NEXT t%
                        IF i% > 0 THEN '                        subscript error trap. Don't pass a zero stack to Pop function
                            DO
                                a% = Pop(fromPile) '            Pump & Dump from stack of those cards accepted by move
                                i% = i% - 1 '                   pop only as many as were moved
                            LOOP UNTIL i% = 0
                        END IF

                    END IF
                END IF
            ELSE '                                              no face up cards are present in the stack
                IF d% = 0 THEN '                                no face down cards are present in the stack
                    Analyze_Stack df%, uf%, fromPile
                    IF fromPile = 1 THEN
                        'IF NOT tranfer is to skip out of subscript error of clicking an empty tableau
                        IF NOT transfer THEN
                            IF deck(stack(fromPile, df% + uf% - 1)).rk = 13 THEN 'only a king should go on an empty stack          SUBSCRIPT ERROR
                                Push Pop(1), x%, 0
                            END IF
                        END IF
                    ELSE
                        IF df% + uf% <= 0 THEN EXIT SUB '       no card to move, leave before subscript error
                        GOSUB grab_face_ups
                        IF deck(pick%(0)).rk = 13 THEN '        if first card is a king. SUBSCRIPT OUT OF RANGE ERROR WHEN EMPTY
                            FOR t% = 0 TO UBOUND(pick%)
                                stack(x%, d% + u% + t%) = pick%(t%)
                                stack(fromPile, df% + t%) = 0 ' empty from stack elements
                            NEXT t%
                            fromPile = 0
                        END IF
                    END IF
                ELSE
                    transfer = NOT transfer
                    IF d% > 0 THEN '                                if there are face down cards,
                        deck(stack(x%, d% - 1)).fc = -1 '           flip the last card in the stack
                    END IF
                END IF
            END IF '                                            end: face up cards present in stack test
    END SELECT
    IF InRegion%(ms, sbut) THEN
        IF UpCheck% THEN
            DO
                flg% = FALSE
                FOR a% = 1 TO 12
                    SELECT CASE a%
                        CASE 2 TO 5
                            _CONTINUE
                        CASE ELSE
                            Analyze_Stack d%, u%, a%
                            IF d% + u% = 0 THEN _CONTINUE
                            flg% = TRUE
                            f% = deck(stack(a%, d% + u% - 1)).st
                            Analyze_Stack df%, uf%, f%
                            IF deck(stack(a%, d% + u% - 1)).rk - 1 = deck(stack(f%, df% + uf% - 1)).rk THEN
                                Push Pop(a%), f%, 0
                            END IF
                    END SELECT
                NEXT a%
            LOOP UNTIL NOT flg%
        END IF
    END IF
    EXIT SUB
    grab_face_ups:
    REDIM pick%(uf% - 1)
    FOR a% = 0 TO uf% - 1
        pick%(a%) = stack(fromPile, df% + a%) 'put all face up cards in frompile into pick array
    NEXT a%
    RETURN
END SUB 'Mouse_Left

'---------------------------------------------------------------
SUB Mouse_Right (ms AS V2)
    DIM x%, d%, u%, rd%, ru%, pt%, t%, a%, tabl%, solve%
    FOR x% = 0 TO 12
        IF InRegion(ms, tpstk(x%)) THEN EXIT FOR
    NEXT x%
    SELECT CASE x%
        CASE 1, 6 TO 12
            IF stack(0, 0) = 0 AND stack(1, 0) = 0 THEN '       when stock and waste piles are empty
                solve% = TRUE
                FOR a% = 1 TO 52
                    IF deck(a%).fc = FALSE THEN solve% = FALSE 'if any card not face up, we aren't solved yet
                NEXT a%
                IF solve% THEN
                    FOR a% = 2 TO 5
                        Analyze_Stack d%, u%, a%
                        FOR tabl% = 6 TO 12
                            Analyze_Stack rd%, ru%, tabl%
                            IF rd% + ru% > 0 THEN
                                IF deck(stack(tabl%, rd% + ru% - 1)).st = a% THEN 'If suit matches
                                    IF deck(stack(tabl%, rd% + ru% - 1)).rk = deck(stack(a%, d% + u%)).rk + 1 THEN
                                        Push Pop(tabl%), a%, 0
                                        'animation here?
                                        '
                                    END IF
                                END IF
                            END IF
                        NEXT tabl%

                    NEXT a%
                END IF
            END IF
            Analyze_Stack d%, u%, x% '                          determine the suit of the last card in stack x%
            IF d% + u% > 0 THEN '                               trap for subscript error
                t% = d% + u% - 1
                IF deck(stack(x%, t%)).fc = FALSE THEN EXIT SUB 'do not transfer a face down card
                pt% = deck(stack(x%, t%)).st '                  create a pointer to the appropriate suit stack 2-5
                Analyze_Stack rd%, ru%, pt% '                   poll state of pointer stack
                IF deck(stack(x%, t%)).rk = ru% + 1 THEN '      if that card is .rk+1 equal to last card in the suit stack
                    stack(pt%, ru%) = stack(x%, t%) '           transfer to that suit stack
                    stack(x%, t%) = 0 '                         erase from x% stack
                END IF
                deck(stack(pt%, ru%)).fc = TRUE
            END IF
    END SELECT
END SUB 'Mouse_Right

'---------------------------------------------------------------
FUNCTION Negative& (var AS LONG)
    Negative& = _RGBA32(255 - _RED32(var), 255 - _GREEN32(var), 255 - _BLUE32(var), _ALPHA32(var))
END FUNCTION 'Negative&

'---------------------------------------------------------------
FUNCTION Pop (stk AS INTEGER)
    DIM dn%, up%
    Analyze_Stack dn%, up%, stk
    Pop = stack(stk, dn% + up% - 1) '                           return topmost array value, accounting for 0 element
    stack(stk, dn% + up% - 1) = 0 '                             clear topmost array element
END FUNCTION 'Pop

'---------------------------------------------------------------
SUB Push (var AS INTEGER, stk AS INTEGER, flip AS INTEGER)
    DIM dn%, up%
    Analyze_Stack dn%, up%, stk
    stack(stk, dn% + up%) = var '                               push value to next array element
    IF flip THEN deck(var).fc = NOT deck(var).fc '              turn over card if flip = TRUE
END SUB 'Push

'---------------------------------------------------------------
SUB Shuffle (arr() AS INTEGER)
    DIM i%, ran%
    RANDOMIZE TIMER
    FOR i% = 1 TO 52
        ran% = INT(RND * 52) + 1
        SWAP arr(i%), arr(ran%)
    NEXT i%
END SUB 'Shuffle

'---------------------------------------------------------------
FUNCTION Rank_Name$ (var AS card)
    SELECT CASE var.rk
        CASE 1: Rank_Name$ = "Ace"
        CASE 2: Rank_Name$ = "Two"
        CASE 3: Rank_Name$ = "Three"
        CASE 4: Rank_Name$ = "Four"
        CASE 5: Rank_Name$ = "Five"
        CASE 6: Rank_Name$ = "Six"
        CASE 7: Rank_Name$ = "Seven"
        CASE 8: Rank_Name$ = "Eight"
        CASE 9: Rank_Name$ = "Nine"
        CASE 10: Rank_Name$ = "Ten"
        CASE 11: Rank_Name$ = "Jack"
        CASE 12: Rank_Name$ = "Queen"
        CASE 13: Rank_Name$ = "King"
    END SELECT
END FUNCTION 'Rank_Name$

'---------------------------------------------------------------
FUNCTION Suit_Name$ (var AS card)
    SELECT CASE var.st
        CASE 2: Suit_Name$ = "Clubs"
        CASE 3: Suit_Name$ = "Hearts"
        CASE 4: Suit_Name$ = "Spades"
        CASE 5: Suit_Name$ = "Diamonds"
    END SELECT
END FUNCTION 'Suit_Name

'---------------------------------------------------------------
FUNCTION Victory_Check%
    DIM x%
    Victory_Check% = TRUE
    FOR x% = 2 TO 5
        IF stack(x%, 12) = 0 THEN
            Victory_Check% = FALSE
        ELSE
            IF deck(stack(x%, 12)).rk MOD 13 <> 0 THEN Victory_Check% = FALSE
        END IF
    NEXT x%
END FUNCTION 'Victory_Check

'---------------------------------------------------------------  under development for eventual fullscreen version
SUB Set_Stacks (w AS INTEGER, h AS INTEGER)
    DIM x10%, y10%, x20%, y20%
    x10% = 10 * (w / _WIDTH(Main&)): y10% = 10
    x20% = 20 * (w / _WIDTH(Main&))
    'tpstk(0).ul.x = x10%: tpstk(0).ul.y = y10%: tpstk(0).lr.x = SW + x10%: tpstk(0).lr.y = SH + y10% 'draw stack
    'x10% = x10% + 10 + SW
    'tpstk(1).ul.x = x10%: tpstk(1).ul.y = y10%: tpstk(1).lr.x = SW + x10%: tpstk(1).lr.y = SH + y10% 'discard stack
    'x10% = x10% + 3 * SW
    'tpstk(2).ul.x = x10%: tpstk(2).ul.y = y10%: tpstk(2).lr.x = SW + x10%: tpstk(2).lr.y = SH + y10% 'clubs stack
    'x10% = x10% + 10 + SW
    'tpstk(3).ul.x = x10%: tpstk(3).ul.y = y10%: tpstk(3).lr.x = SW + x10%: tpstk(3).lr.y = SH + y10% 'hearts stack
    'x10% = x10% + 10 + SW
    'tpstk(4).ul.x = x10%: tpstk(4).ul.y = y10%: tpstk(4).lr.x = SW + x10%: tpstk(4).lr.y = SH + y10% 'spades stack
    'x10% = x10% + 10 + SW
    'tpstk(5).ul.x = x10%: tpstk(5).ul.y = y10%: tpstk(5).lr.x = SW + x10%: tpstk(5).lr.y = SH + y10% 'diamonds stack
    'x10% = 10: y10% = y10% + SH + 50
    'tpstk(6).ul.x = x10%: tpstk(6).ul.y = y10%: tpstk(6).lr.x = x10% + SW: tpstk(6).lr.y = _HEIGHT - 1 'build 1 stack
    'x10% = x10% + 20 + SW
    'tpstk(7).ul.x = x10%: tpstk(7).ul.y = y10%: tpstk(7).lr.x = x10% + SW: tpstk(7).lr.y = _HEIGHT - 1 'build 2 stack
    'x10% = x10% + 20 + SW
    'tpstk(8).ul.x = x10%: tpstk(8).ul.y = y10%: tpstk(8).lr.x = x10% + SW: tpstk(8).lr.y = _HEIGHT - 1 'build 3 stack
    'x10% = x10% + 20 + SW
    'tpstk(9).ul.x = x10%: tpstk(9).ul.y = y10%: tpstk(9).lr.x = x10% + SW: tpstk(9).lr.y = _HEIGHT - 1 'build 4 stack
    'x10% = x10% + 20 + SW
    'tpstk(10).ul.x = x10%: tpstk(10).ul.y = y10%: tpstk(10).lr.x = x10% + SW: tpstk(10).lr.y = _HEIGHT - 1 'build 5 stack
    'x10% = x10% + 20 + SW
    'tpstk(11).ul.x = x10%: tpstk(11).ul.y = y10%: tpstk(11).lr.x = x10% + SW: tpstk(11).lr.y = _HEIGHT - 1 'build 6 stack
    'x10% = x10% + 20 + SW
    'tpstk(12).ul.x = x10%: tpstk(12).ul.y = y10%: tpstk(12).lr.x = x10% + SW: tpstk(12).lr.y = _HEIGHT - 1 'build 7 stack

END SUB 'Set_Stacks

'---------------------------------------------------------------
FUNCTION UpCheck%
    DIM x%, s%
    s% = TRUE
    FOR x% = 1 TO 52
        IF deck(x%).fc = FALSE THEN s% = FALSE: EXIT FOR
    NEXT x%
    UpCheck% = s%
END FUNCTION 'UpCheck%

'---------------------------------------------------------------
SUB Save_Hand
    DIM f&
    DIM x%, s%, c%
    f& = FREEFILE
    OPEN "hand.bin" FOR BINARY AS f&
    FOR x% = 1 TO 52
        PUT f&, , deck(x%)
    NEXT x%
    FOR s% = 0 TO 12
        FOR c% = 0 TO 52
            PUT f&, , stack(s%, c%)
        NEXT c%
    NEXT s%
    CLOSE f&
END SUB 'Save_Hand

'---------------------------------------------------------------
SUB Load_Hand
    DIM f&
    DIM x%, s%, c%
    f& = FREEFILE
    IF _FILEEXISTS("hand.bin") THEN
        OPEN "hand.bin" FOR BINARY AS f&
        FOR x% = 1 TO 52
            GET f&, , deck(x%)
        NEXT x%
        FOR s% = 0 TO 12
            FOR c% = 0 TO 52
                GET f&, , stack(s%, c%)
            NEXT c%
        NEXT s%
        CLOSE f&
    END IF
END SUB 'Load_Hand
DO: LOOP: DO: LOOP
sha_na_na_na_na_na_na_na_na_na:
Reply
#12
Added animation to the card moves. All updates are in the original post and attachment.
DO: LOOP: DO: LOOP
sha_na_na_na_na_na_na_na_na_na:
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)