Java Docs

Go here to see the full Java Docs. A link to the actual Java source code for each class is in their respective documentation.

The solitaire game engine code is based off of a C++ version. The source for the GUI packages, view and view.awt, are pretty much crap. This was my first GUI in Java and a lot of hacking was done to get descent drag and drop performance.

I stopped working on the Java version when I started working on nyse.com.

Code Sample

Here is a source code sample. This is card.games.Canfield.java which creates and defines Canfield.

If it helps, note that my set methods always return a this which enables code like:

	somePile.available(...).build(...).deal(...);
	
which is equavalent to:
	somePile.available(...); somePile.build(...); somePile.deal(...);


/*
 * Copyright (c) 1999 David Mannies.  All Rights Reserved.
 */

package card.game;

import card.*;
import java.util.*;


/**
 * <A href="javascript:window.location = window.location.href.substring(0, window.location.href.indexOf('.')) + '.java.html'">view source</A><BR><BR>
 * 
 * Class for generating Canfield game setup.
 *
 * @author   David Mannies
 */
public class Canfield extends card.Game
{
    //**************************  PUBLIC METHODS  ******************************
    /**
     * Default constructor.
     */
    public Canfield()
    {}
    
    class SetFoundationStart extends card.Event
    {
        public card.build.Exact exact()
        {return exact_;}
        
        public SetFoundationStart exact(card.build.Exact e)
        {exact_ = e; return this;}
        
        protected boolean doHandleEvent(Parameters p)
        {
            if(p.pile().cards().size() > 0)
            {
                Card card = p.pile().cards().firstCard();
                
                exact().card(new card.Card().value(card.value()));
            }
                
            return true;
        }
        
        card.build.Exact exact_ = null;
    }

    protected Pile doGetAutoPlay(Pile to, Pile from, Card card)
    {
        Pile ret = to;
        
        // stop moving of top card back and forth
        if(to != null)
            if(from.type() == Pile.TYPE_TABLEAU && to.type() == Pile.TYPE_TABLEAU)
                if(display(from) != card)
                    ret = null;
        
        return ret;
    }

    
    //************************  PROTECTED METHODS  *****************************
    /**
     * Does actual object creation for this game.
     */
    protected void doCreate()
    {
        deck(new card.deck.Standard());
        
        layout(new Layout().x(6.5).y(2));

        indexStart(createPiles(11));
        indexEnd(indexStart() + 12 - 1);
        
        int index = indexStart();

        //foundation
        int foundationIndex = index;
        card.build.Exact exact = new card.build.Exact();
        for(int loop =0; loop<4; loop++)
            ((Pile)piles().elementAt(index++))
                .available(new card.available.Top())
                .build(new card.build.Count().count(1).first(exact).and(new card.build.Suit(card.build.Suit.SAME).and(new card.build.Value(card.build.Value.UP).continuous(true))))
                .deal(((loop == 0) ? (new card.deal.All().count(1).next(new card.deal.Show(card.deal.Show.ALL))) : (Deal)null))
                .type(card.Pile.TYPE_FOUNDATION)
                .layout(new Layout().x(2.5 + loop).y(0).layout(card.Layout.LAYOUT_STACK | card.Layout.LAYOUT_DISPLAY_EMPTY))
                ;
        ((Pile)piles().elementAt(foundationIndex))
            .event(new SetFoundationStart().exact(exact).events(card.Event.EVENT_START))
            ;

        //reserve
        int reserveIndex = indexStart();
        ((Pile)piles().elementAt(reserveIndex = index++))
            .available(new card.available.Top())
            .build((Build)null)
            .deal(new card.deal.All().count(13).next(new card.deal.Show(card.deal.Show.ALL)))
            .type(card.Pile.TYPE_RESERVE)
            .layout(new Layout().x(1).y(1).layout(card.Layout.LAYOUT_VERTICAL | card.Layout.LAYOUT_FEATHER).maxFacing(13).maxFacingTypical(13))
            ;

        //stock
        ((Pile)piles().elementAt(index++))
            .build((Build)null)
            .deal(new card.deal.All().count(34).next(new card.deal.Show(card.deal.Show.ALL)))
            .type(card.Pile.TYPE_STOCK)
            .layout(new Layout().x(0).y(0).layout(card.Layout.LAYOUT_DISPLAY_AS_HIDDEN))
            .event(new card.event.TurnCard().to(index).events(card.Event.EVENT_SELECTED))
            ;

        //discard
        ((Pile)piles().elementAt(index++))
            .available(new card.available.Top())
            .build((Build)null)
            .deal((Deal)null)
            .type(card.Pile.TYPE_DISCARD)
            .layout(new Layout().x(1).y(0))
            ;

        //tableau
        for(int loop =0; loop<4; loop++)
            ((Pile)piles().elementAt(index++))
                .available(new card.available.Display().or(new card.available.Top()))
                .build(new card.build.Suit(card.build.Suit.ALTERNATE).and(new card.build.Value(card.build.Value.DOWN).continuous(true)))
                .deal(new card.deal.All().count(1).next(new card.deal.Show(card.deal.Show.ALL)))
                .type(card.Pile.TYPE_TABLEAU)
                .layout(new Layout().x(2.5 + loop).y(1).layout(card.Layout.LAYOUT_VERTICAL | card.Layout.LAYOUT_SPREAD).maxFacing(13).maxFacingTypical(8))
                .event(new card.event.GetCard().from(reserveIndex).events(card.Event.EVENT_EMPTY))
                ;
    }
}