renaming and moving samples around

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@5300 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2000-01-08 15:28:31 +00:00
parent 617ec45690
commit 70d26c3f4f
167 changed files with 137 additions and 0 deletions

1
demos/forty/.cvsignore Normal file
View File

@@ -0,0 +1 @@

21
demos/forty/Makefile.in Normal file
View File

@@ -0,0 +1,21 @@
#
# File: Makefile.in
# Author: Julian Smart
# Created: 1998
# Updated:
# Copyright: (c) 1998 Julian Smart
#
# "%W% %G%"
#
# Makefile for forty example (UNIX).
top_srcdir = @top_srcdir@
top_builddir = ../..
program_dir = samples/forty
PROGRAM=forty
OBJECTS=$(PROGRAM).o canvas.o card.o game.o pile.o playerdg.o scoredg.o scorefil.o
include ../../src/makeprog.env

253
demos/forty/canvas.cpp Normal file
View File

@@ -0,0 +1,253 @@
/////////////////////////////////////////////////////////////////////////////
// Name: canvas.cpp
// Purpose: Forty Thieves patience game
// Author: Chris Breeze
// Modified by:
// Created: 21/07/97
// RCS-ID: $Id$
// Copyright: (c) 1993-1998 Chris Breeze
// Licence: wxWindows licence
//---------------------------------------------------------------------------
// Last modified: 22nd July 1998 - ported to wxWindows 2.0
/////////////////////////////////////////////////////////////////////////////
#ifdef __GNUG__
#pragma implementation
#pragma interface
#endif
// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
#include "forty.h"
#include "card.h"
#include "game.h"
#include "scorefil.h"
#include "playerdg.h"
#include "canvas.h"
BEGIN_EVENT_TABLE(FortyCanvas, wxScrolledWindow)
EVT_MOUSE_EVENTS(FortyCanvas::OnMouseEvent)
END_EVENT_TABLE()
FortyCanvas::FortyCanvas(wxWindow* parent, int x, int y, int w, int h) :
wxScrolledWindow(parent, -1, wxPoint(x, y), wxSize(w, h)),
m_helpingHand(TRUE),
m_rightBtnUndo(TRUE),
m_playerDialog(0),
m_leftBtnDown(FALSE)
{
#ifdef __WXGTK__
m_font = wxTheFontList->FindOrCreateFont(12, wxROMAN, wxNORMAL, wxNORMAL);
#else
m_font = wxTheFontList->FindOrCreateFont(10, wxSWISS, wxNORMAL, wxNORMAL);
#endif
SetBackgroundColour(FortyApp::BackgroundColour());
m_handCursor = new wxCursor(wxCURSOR_HAND);
m_arrowCursor = new wxCursor(wxCURSOR_ARROW);
wxString name = wxTheApp->GetAppName();
if (name.Length() <= 0) name = "forty";
m_scoreFile = new ScoreFile(name);
m_game = new Game(0, 0, 0);
m_game->Deal();
}
FortyCanvas::~FortyCanvas()
{
UpdateScores();
delete m_game;
delete m_scoreFile;
}
/*
Write the current player's score back to the score file
*/
void FortyCanvas::UpdateScores()
{
if (m_player.Length() > 0 && m_scoreFile && m_game)
{
m_scoreFile->WritePlayersScore(
m_player,
m_game->GetNumWins(),
m_game->GetNumGames(),
m_game->GetScore()
);
}
}
void FortyCanvas::OnDraw(wxDC& dc)
{
dc.SetFont(* m_font);
m_game->Redraw(dc);
// if player name not set (and selection dialog is not displayed)
// then ask the player for their name
if (m_player.Length() == 0 && !m_playerDialog)
{
m_playerDialog = new PlayerSelectionDialog(this, m_scoreFile);
m_playerDialog->ShowModal();
m_player = m_playerDialog->GetPlayersName();
if (m_player.Length() > 0)
{
// user entered a name - lookup their score
int wins, games, score;
m_scoreFile->ReadPlayersScore(m_player, wins, games, score);
m_game->NewPlayer(wins, games, score);
m_game->DisplayScore(dc);
m_playerDialog->Destroy();
m_playerDialog = 0;
Refresh();
}
else
{
// user cancelled the dialog - exit the app
((wxFrame*)GetParent())->Close(TRUE);
}
}
}
/*
Called when the main frame is closed
*/
bool FortyCanvas::OnCloseCanvas()
{
if (m_game->InPlay() &&
wxMessageBox("Are you sure you want to\nabandon the current game?",
"Warning", wxYES_NO | wxICON_QUESTION) == wxNO)
{
return FALSE;
}
return TRUE;
}
void FortyCanvas::OnMouseEvent(wxMouseEvent& event)
{
int mouseX = (int)event.GetX();
int mouseY = (int)event.GetY();
wxClientDC dc(this);
PrepareDC(dc);
dc.SetFont(* m_font);
if (event.LeftDClick())
{
if (m_leftBtnDown)
{
m_leftBtnDown = FALSE;
ReleaseMouse();
m_game->LButtonUp(dc, mouseX, mouseY);
}
m_game->LButtonDblClk(dc, mouseX, mouseY);
}
else if (event.LeftDown())
{
if (!m_leftBtnDown)
{
m_leftBtnDown = TRUE;
CaptureMouse();
m_game->LButtonDown(dc, mouseX, mouseY);
}
}
else if (event.LeftUp())
{
if (m_leftBtnDown)
{
m_leftBtnDown = FALSE;
ReleaseMouse();
m_game->LButtonUp(dc, mouseX, mouseY);
}
}
else if (event.RightDown() && !event.LeftIsDown())
{
// only allow right button undo if m_rightBtnUndo is TRUE
if (m_rightBtnUndo)
{
if (event.ControlDown() || event.ShiftDown())
{
m_game->Redo(dc);
}
else
{
m_game->Undo(dc);
}
}
}
else if (event.Dragging())
{
m_game->MouseMove(dc, mouseX, mouseY);
}
if (!event.LeftIsDown())
{
SetCursorStyle(mouseX, mouseY);
}
}
void FortyCanvas::SetCursorStyle(int x, int y)
{
if (m_game->HaveYouWon())
{
if (wxMessageBox("Do you wish to play again?",
"Well Done, You have won!", wxYES_NO | wxICON_QUESTION) == wxYES)
{
m_game->Deal();
wxClientDC dc(this);
PrepareDC(dc);
dc.SetFont(* m_font);
m_game->Redraw(dc);
}
else
{
// user cancelled the dialog - exit the app
((wxFrame*)GetParent())->Close(TRUE);
}
}
// Only set cursor to a hand if 'helping hand' is enabled and
// the card under the cursor can go somewhere
if (m_game->CanYouGo(x, y) && m_helpingHand)
{
SetCursor(* m_handCursor);
}
else
{
SetCursor(* m_arrowCursor);
}
}
void FortyCanvas::NewGame()
{
m_game->Deal();
Refresh();
}
void FortyCanvas::Undo()
{
wxClientDC dc(this);
PrepareDC(dc);
dc.SetFont(* m_font);
m_game->Undo(dc);
}
void FortyCanvas::Redo()
{
wxClientDC dc(this);
PrepareDC(dc);
dc.SetFont(* m_font);
m_game->Redo(dc);
}

56
demos/forty/canvas.h Normal file
View File

@@ -0,0 +1,56 @@
/////////////////////////////////////////////////////////////////////////////
// Name: canvas.h
// Purpose: Forty Thieves patience game
// Author: Chris Breeze
// Modified by:
// Created: 21/07/97
// RCS-ID: $Id$
// Copyright: (c) 1993-1998 Chris Breeze
// Licence: wxWindows licence
//---------------------------------------------------------------------------
// Last modified: 22nd July 1998 - ported to wxWindows 2.0
/////////////////////////////////////////////////////////////////////////////
#ifndef _CANVAS_H_
#define _CANVAS_H_
class Card;
class Game;
class ScoreFile;
class PlayerSelectionDialog;
class FortyCanvas: public wxScrolledWindow
{
public:
FortyCanvas(wxWindow* parent, int x, int y, int w, int h);
virtual ~FortyCanvas();
virtual void OnDraw(wxDC& dc);
bool OnCloseCanvas();
void OnMouseEvent(wxMouseEvent& event);
void SetCursorStyle(int x, int y);
void NewGame();
void Undo();
void Redo();
ScoreFile* GetScoreFile() const { return m_scoreFile; }
void UpdateScores();
void EnableHelpingHand(bool enable) { m_helpingHand = enable; }
void EnableRightButtonUndo(bool enable) { m_rightBtnUndo = enable; }
DECLARE_EVENT_TABLE()
private:
wxFont* m_font;
Game* m_game;
ScoreFile* m_scoreFile;
wxCursor* m_arrowCursor;
wxCursor* m_handCursor;
bool m_helpingHand;
bool m_rightBtnUndo;
wxString m_player;
PlayerSelectionDialog* m_playerDialog;
bool m_leftBtnDown;
};
#endif

358
demos/forty/card.cpp Normal file
View File

@@ -0,0 +1,358 @@
/////////////////////////////////////////////////////////////////////////////
// Name: card.cpp
// Purpose: Forty Thieves patience game
// Author: Chris Breeze
// Modified by:
// Created: 21/07/97
// RCS-ID: $Id$
// Copyright: (c) 1993-1998 Chris Breeze
// Licence: wxWindows licence
//---------------------------------------------------------------------------
// Last modified: 22nd July 1998 - ported to wxWindows 2.0
/////////////////////////////////////////////////////////////////////////////
//+-------------------------------------------------------------+
//| Description
//| A class for drawing playing cards.
//| Currently assumes that the card symbols have been
//| loaded into hbmap_symbols and the pictures for the
//| Jack, Queen and King have been loaded into
//| hbmap_pictures.
//+-------------------------------------------------------------+
#ifdef __GNUG__
#pragma implementation
#pragma interface
#endif
// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "forty.h"
#include "card.h"
#if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXMAC__)
#include "pictures.xpm"
#include "symbols.xbm"
#endif
wxBitmap* Card::m_pictureBmap = 0;
wxBitmap* Card::m_symbolBmap = 0;
//+-------------------------------------------------------------+
//| Card::Card() |
//+-------------------------------------------------------------+
//| Description: |
//| Constructor for a playing card. |
//| Checks that the value is in the range 1..52 and then |
//| initialises the suit, colour, pipValue and wayUp. |
//+-------------------------------------------------------------+
Card::Card(int value, WayUp way_up) :
m_wayUp(way_up)
{
if (!m_symbolBmap)
{
#ifdef __WXMSW__
m_symbolBmap = new wxBitmap("CardSymbols", wxBITMAP_TYPE_BMP_RESOURCE);
#else
m_symbolBmap = new wxBitmap(Symbols_bits, Symbols_width, Symbols_height);
#endif
if (!m_symbolBmap->Ok())
{
::wxMessageBox("Failed to load bitmap CardSymbols", "Error");
}
}
if (!m_pictureBmap)
{
#ifdef __WXMSW__
m_pictureBmap = new wxBitmap("CardPictures", wxBITMAP_TYPE_BMP_RESOURCE);
#else
m_pictureBmap = new wxBitmap(Pictures);
#endif
if (!m_pictureBmap->Ok())
{
::wxMessageBox("Failed to load bitmap CardPictures", "Error");
}
}
if (value >= 1 && value <= PackSize)
{
switch ((value - 1) / 13)
{
case 0:
m_suit = clubs;
m_colour = black;
break;
case 1:
m_suit = diamonds;
m_colour = red;
break;
case 2:
m_suit = hearts;
m_colour = red;
break;
case 3:
m_suit = spades;
m_colour = black;
break;
}
m_pipValue = 1 + (value - 1) % 13;
m_status = TRUE;
}
else
{
m_status = FALSE;
}
} // Card::Card()
//+-------------------------------------------------------------+
//| Card::~Card() |
//+-------------------------------------------------------------+
//| Description: |
//| Destructor - nothing to do at present. |
//+-------------------------------------------------------------+
Card::~Card()
{
}
//+-------------------------------------------------------------+
//| Card::Erase() |
//+-------------------------------------------------------------+
//| Description: |
//| Erase the card at (x, y) by drawing a rectangle in the |
//| background colour. |
//+-------------------------------------------------------------+
void Card::Erase(wxDC& dc, int x, int y)
{
wxPen* pen = wxThePenList->FindOrCreatePen(
FortyApp::BackgroundColour(),
1,
wxSOLID
);
dc.SetPen(* pen);
dc.SetBrush(FortyApp::BackgroundBrush());
dc.DrawRectangle(x, y, CardWidth, CardHeight);
} // Card::Erase()
//+-------------------------------------------------------------+
//| Card::Draw() |
//+-------------------------------------------------------------+
//| Description: |
//| Draw the card at (x, y). |
//| If the card is facedown draw the back of the card. |
//| If the card is faceup draw the front of the card. |
//| Cards are not held in bitmaps, instead they are drawn |
//| from their constituent parts when required. |
//| hbmap_symbols contains large and small suit symbols and |
//| pip values. These are copied to the appropriate part of |
//| the card. Picture cards use the pictures defined in |
//| hbmap_pictures. Note that only one picture is defined |
//| for the Jack, Queen and King, unlike a real pack where |
//| each suit is different. |
//| |
//| WARNING: |
//| The locations of these symbols is 'hard-wired' into the |
//| code. Editing the bitmaps or the numbers below will |
//| result in the wrong symbols being displayed. |
//+-------------------------------------------------------------+
void Card::Draw(wxDC& dc, int x, int y)
{
wxBrush backgroundBrush( dc.GetBackground() );
dc.SetBrush(* wxWHITE_BRUSH);
dc.SetPen(* wxBLACK_PEN);
dc.DrawRoundedRectangle(x, y, CardWidth, CardHeight, 4);
if (m_wayUp == facedown)
{
dc.SetBackground(* wxRED_BRUSH);
dc.SetBackgroundMode(wxSOLID);
wxBrush* brush = wxTheBrushList->FindOrCreateBrush(
"BLACK", wxCROSSDIAG_HATCH
);
dc.SetBrush(* brush);
dc.DrawRoundedRectangle(
x + 4, y + 4,
CardWidth - 8, CardHeight - 8,
2
);
}
else
{
wxMemoryDC memoryDC;
memoryDC.SelectObject(* m_symbolBmap);
// dc.SetBackgroundMode(wxTRANSPARENT);
dc.SetTextBackground(*wxWHITE);
switch (m_suit)
{
case spades:
case clubs:
dc.SetTextForeground(*wxBLACK);
break;
case diamonds:
case hearts:
dc.SetTextForeground(*wxRED);
break;
}
// Draw the value
dc.Blit(x + 3, y + 3, 6, 7,
&memoryDC, 6 * (m_pipValue - 1), 36, wxCOPY);
dc.Blit(x + CardWidth - 9, y + CardHeight - 11, 6, 7,
&memoryDC, 6 * (m_pipValue - 1), 43, wxCOPY);
// Draw the pips
dc.Blit(x + 11, y + 3, 7, 7,
&memoryDC, 7 * m_suit, 0, wxCOPY);
dc.Blit(x + CardWidth - 17, y + CardHeight - 11, 7, 7,
&memoryDC, 7 * m_suit, 7, wxCOPY);
switch (m_pipValue)
{
case 1:
dc.Blit(x - 5 + CardWidth / 2, y - 5 + CardHeight / 2, 11, 11,
&memoryDC, 11 * m_suit, 14, wxCOPY);
break;
case 3:
dc.Blit(x - 5 + CardWidth / 2, y - 5 + CardHeight / 2, 11, 11,
&memoryDC, 11 * m_suit, 14, wxCOPY);
case 2:
dc.Blit(x - 5 + CardWidth / 2,
y - 5 + CardHeight / 4, 11, 11,
&memoryDC, 11 * m_suit, 14, wxCOPY);
dc.Blit(x - 5 + CardWidth / 2,
y - 5 + 3 * CardHeight / 4, 11, 11,
&memoryDC, 11 * m_suit, 25, wxCOPY);
break;
case 5:
dc.Blit(x - 5 + CardWidth / 2, y - 5 + CardHeight / 2, 11, 11,
&memoryDC, 11 * m_suit, 14, wxCOPY);
case 4:
dc.Blit(x - 5 + CardWidth / 4,
y - 5 + CardHeight / 4, 11, 11,
&memoryDC, 11 * m_suit, 14, wxCOPY);
dc.Blit(x - 5 + CardWidth / 4,
y - 5 + 3 * CardHeight / 4, 11, 11,
&memoryDC, 11 * m_suit, 25, wxCOPY);
dc.Blit(x - 5 + 3 * CardWidth / 4,
y - 5 + CardHeight / 4, 11, 11,
&memoryDC, 11 * m_suit, 14, wxCOPY);
dc.Blit(x - 5 + 3 * CardWidth / 4,
y - 5 + 3 * CardHeight / 4, 11, 11,
&memoryDC, 11 * m_suit, 25, wxCOPY);
break;
case 8:
dc.Blit(x - 5 + 5 * CardWidth / 10,
y - 5 + 5 * CardHeight / 8, 11, 11,
&memoryDC, 11 * m_suit, 25, wxCOPY);
case 7:
dc.Blit(x - 5 + 5 * CardWidth / 10,
y - 5 + 3 * CardHeight / 8, 11, 11,
&memoryDC, 11 * m_suit, 14, wxCOPY);
case 6:
dc.Blit(x - 5 + CardWidth / 4,
y - 5 + CardHeight / 4, 11, 11,
&memoryDC, 11 * m_suit, 14, wxCOPY);
dc.Blit(x - 5 + CardWidth / 4,
y - 5 + CardHeight / 2, 11, 11,
&memoryDC, 11 * m_suit, 14, wxCOPY);
dc.Blit(x - 5 + CardWidth / 4,
y - 5 + 3 * CardHeight / 4, 11, 11,
&memoryDC, 11 * m_suit, 25, wxCOPY);
dc.Blit(x - 5 + 3 * CardWidth / 4,
y - 5 + CardHeight / 4, 11, 11,
&memoryDC, 11 * m_suit, 14, wxCOPY);
dc.Blit(x - 5 + 3 * CardWidth / 4,
y - 5 + CardHeight / 2, 11, 11,
&memoryDC, 11 * m_suit, 14, wxCOPY);
dc.Blit(x - 5 + 3 * CardWidth / 4,
y - 5 + 3 * CardHeight / 4, 11, 11,
&memoryDC, 11 * m_suit, 25, wxCOPY);
break;
case 10:
dc.Blit(x - 5 + CardWidth / 2,
y - 5 + 2 * CardHeight / 3, 11, 11,
&memoryDC, 11 * m_suit, 25, wxCOPY);
case 9:
dc.Blit(x - 5 + CardWidth / 4,
y - 6 + CardHeight / 4, 11, 11,
&memoryDC, 11 * m_suit, 14, wxCOPY);
dc.Blit(x - 5 + CardWidth / 4,
y - 6 + 5 * CardHeight / 12, 11, 11,
&memoryDC, 11 * m_suit, 14, wxCOPY);
dc.Blit(x - 5 + CardWidth / 4,
y - 5 + 7 * CardHeight / 12, 11, 11,
&memoryDC, 11 * m_suit, 25, wxCOPY);
dc.Blit(x - 5 + CardWidth / 4,
y - 5 + 3 * CardHeight / 4, 11, 11,
&memoryDC, 11 * m_suit, 25, wxCOPY);
dc.Blit(x - 5 + 3 * CardWidth / 4,
y - 6 + CardHeight / 4, 11, 11,
&memoryDC, 11 * m_suit, 14, wxCOPY);
dc.Blit(x - 5 + 3 * CardWidth / 4,
y - 6 + 5 * CardHeight / 12, 11, 11,
&memoryDC, 11 * m_suit, 14, wxCOPY);
dc.Blit(x - 5 + 3 * CardWidth / 4,
y - 5 + 7 * CardHeight / 12, 11, 11,
&memoryDC, 11 * m_suit, 25, wxCOPY);
dc.Blit(x - 5 + 3 * CardWidth / 4,
y - 5 + 3 * CardHeight / 4, 11, 11,
&memoryDC, 11 * m_suit, 25, wxCOPY);
dc.Blit(x - 5 + CardWidth / 2,
y - 5 + CardHeight / 3, 11, 11,
&memoryDC, 11 * m_suit, 14, wxCOPY);
break;
case 11:
case 12:
case 13:
memoryDC.SelectObject(* m_pictureBmap);
dc.Blit(x + 5, y - 5 + CardHeight / 4, 40, 45,
&memoryDC, 40 * (m_pipValue - 11), 0, wxCOPY);
memoryDC.SelectObject(* m_symbolBmap);
dc.Blit(x + 32, y - 3 + CardHeight / 4, 11, 11,
&memoryDC, 11 * m_suit, 14, wxCOPY);
dc.Blit(x + 7, y + 27 + CardHeight / 4, 11, 11,
&memoryDC, 11 * m_suit, 25, wxCOPY);
break;
}
}
dc.SetBackground( backgroundBrush );
} // Card:Draw()
//+-------------------------------------------------------------+
//| Card::DrawNullCard() |
//+-------------------------------------------------------------+
//| Description: |
//| Draws the outline of a card at (x, y). |
//| Used to draw place holders for empty piles of cards. |
//+-------------------------------------------------------------+
void Card::DrawNullCard(wxDC& dc, int x, int y)
{
wxPen* pen = wxThePenList->FindOrCreatePen(FortyApp::TextColour(), 1, wxSOLID);
dc.SetBrush(FortyApp::BackgroundBrush());
dc.SetPen(*pen);
dc.DrawRoundedRectangle(x, y, CardWidth, CardHeight, 4);
} // Card::DrawNullCard()

65
demos/forty/card.h Normal file
View File

@@ -0,0 +1,65 @@
/////////////////////////////////////////////////////////////////////////////
// Name: card.h
// Purpose: Forty Thieves patience game
// Author: Chris Breeze
// Modified by:
// Created: 21/07/97
// RCS-ID: $Id$
// Copyright: (c) 1993-1998 Chris Breeze
// Licence: wxWindows licence
//---------------------------------------------------------------------------
// Last modified: 22nd July 1998 - ported to wxWindows 2.0
/////////////////////////////////////////////////////////////////////////////
//+-------------------------------------------------------------+
//| Description: |
//| A class for drawing playing cards. |
//| InitCards() must be called before using the Card class, |
//| otherwise the card bitmaps will not be loaded. |
//| CloseCards() must be called before terminating the |
//| program so that the bitmaps are deleted and the memory |
//| given back to Windows. |
//+-------------------------------------------------------------+
#ifndef _CARD_H_
#define _CARD_H_
// Constants
const int PackSize = 52;
const int CardWidth = 50;
const int CardHeight = 70;
// Data types
enum Suit { clubs = 0, diamonds = 1, hearts = 2, spades = 3 };
enum SuitColour { red = 0, black = 1 };
enum WayUp { faceup, facedown };
//--------------------------------//
// A class defining a single card //
//--------------------------------//
class Card {
public:
Card(int value, WayUp way_up = facedown);
virtual ~Card();
void Draw(wxDC& pDC, int x, int y);
static void DrawNullCard(wxDC& pDC, int x, int y); // Draw card place-holder
void Erase(wxDC& pDC, int x, int y);
void TurnCard(WayUp way_up = faceup) { m_wayUp = way_up; }
WayUp GetWayUp() const { return m_wayUp; }
int GetPipValue() const { return m_pipValue; }
Suit GetSuit() const { return m_suit; }
SuitColour GetColour() const { return m_colour; }
private:
Suit m_suit;
int m_pipValue; // in the range 1 (Ace) to 13 (King)
SuitColour m_colour; // red or black
bool m_status;
WayUp m_wayUp;
static wxBitmap* m_symbolBmap;
static wxBitmap* m_pictureBmap;
};
#endif // _CARD_H_

BIN
demos/forty/cards.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 B

271
demos/forty/forty.cpp Normal file
View File

@@ -0,0 +1,271 @@
/////////////////////////////////////////////////////////////////////////////
// Name: forty.cpp
// Purpose: Forty Thieves patience game
// Author: Chris Breeze
// Modified by:
// Created: 21/07/97
// RCS-ID: $Id$
// Copyright: (c) 1993-1998 Chris Breeze
// Licence: wxWindows licence
//---------------------------------------------------------------------------
// Last modified: 22nd July 1998 - ported to wxWindows 2.0
/////////////////////////////////////////////////////////////////////////////
#ifdef __GNUG__
#pragma implementation
#pragma interface
#endif
// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
#include "canvas.h"
#include "forty.h"
#include "scoredg.h"
#ifdef wx_x
#include "cards.xbm"
#endif
class FortyFrame: public wxFrame
{
public:
FortyFrame(wxFrame* frame, char* title, int x, int y, int w, int h);
virtual ~FortyFrame();
void OnCloseWindow(wxCloseEvent& event);
// Menu callbacks
void NewGame(wxCommandEvent& event);
void Exit(wxCommandEvent& event);
void About(wxCommandEvent& event);
void Undo(wxCommandEvent& event);
void Redo(wxCommandEvent& event);
void Scores(wxCommandEvent& event);
void ToggleRightButtonUndo(wxCommandEvent& event);
void ToggleHelpingHand(wxCommandEvent& event);
DECLARE_EVENT_TABLE()
private:
enum MenuCommands { NEW_GAME = 10, SCORES, EXIT,
UNDO, REDO,
RIGHT_BUTTON_UNDO, HELPING_HAND,
ABOUT };
wxMenuBar* m_menuBar;
FortyCanvas* m_canvas;
};
BEGIN_EVENT_TABLE(FortyFrame, wxFrame)
EVT_MENU(NEW_GAME, FortyFrame::NewGame)
EVT_MENU(EXIT, FortyFrame::Exit)
EVT_MENU(ABOUT, FortyFrame::About)
EVT_MENU(UNDO, FortyFrame::Undo)
EVT_MENU(REDO, FortyFrame::Redo)
EVT_MENU(SCORES, FortyFrame::Scores)
EVT_MENU(RIGHT_BUTTON_UNDO, FortyFrame::ToggleRightButtonUndo)
EVT_MENU(HELPING_HAND, FortyFrame::ToggleHelpingHand)
EVT_CLOSE(FortyFrame::OnCloseWindow)
END_EVENT_TABLE()
// Create a new application object
IMPLEMENT_APP (FortyApp)
wxColour* FortyApp::m_backgroundColour = 0;
wxColour* FortyApp::m_textColour = 0;
wxBrush* FortyApp::m_backgroundBrush = 0;
bool FortyApp::OnInit()
{
FortyFrame* frame = new FortyFrame(
0,
"Forty Thieves",
-1, -1, 668, 510
);
// Show the frame
frame->Show(TRUE);
return TRUE;
}
const wxColour& FortyApp::BackgroundColour()
{
if (!m_backgroundColour)
{
m_backgroundColour = new wxColour(0, 128, 0);
}
return *m_backgroundColour;
}
const wxBrush& FortyApp::BackgroundBrush()
{
if (!m_backgroundBrush)
{
m_backgroundBrush = new wxBrush(BackgroundColour(), wxSOLID);
}
return *m_backgroundBrush;
}
const wxColour& FortyApp::TextColour()
{
if (!m_textColour)
{
m_textColour = new wxColour("BLACK");
}
return *m_textColour;
}
// My frame constructor
FortyFrame::FortyFrame(wxFrame* frame, char* title, int x, int y, int w, int h):
wxFrame(frame, -1, title, wxPoint(x, y), wxSize(w, h))
{
#ifdef __WXMAC__
// we need this in order to allow the about menu relocation, since ABOUT is not the default id of the about menu
wxApp::s_macAboutMenuItemId = ABOUT ;
#endif
// set the icon
#ifdef __WXMSW__
SetIcon(wxIcon("CardsIcon"));
#else
#ifdef GTK_TBD
SetIcon(wxIcon(Cards_bits, Cards_width, Cards_height));
#endif
#endif
// Make a menu bar
wxMenu* gameMenu = new wxMenu;
gameMenu->Append(NEW_GAME, "&New", "Start a new game");
gameMenu->Append(SCORES, "&Scores...", "Displays scores");
gameMenu->Append(EXIT, "E&xit", "Exits Forty Thieves");
wxMenu* editMenu = new wxMenu;
editMenu->Append(UNDO, "&Undo", "Undo the last move");
editMenu->Append(REDO, "&Redo", "Redo a move that has been undone");
wxMenu* optionsMenu = new wxMenu;
optionsMenu->Append(RIGHT_BUTTON_UNDO,
"&Right button undo",
"Enables/disables right mouse button undo and redo",
TRUE
);
optionsMenu->Append(HELPING_HAND,
"&Helping hand",
"Enables/disables hand cursor when a card can be moved",
TRUE
);
optionsMenu->Check(HELPING_HAND, TRUE);
optionsMenu->Check(RIGHT_BUTTON_UNDO, TRUE);
wxMenu* helpMenu = new wxMenu;
helpMenu->Append(ABOUT, "&About", "Displays program version information");
m_menuBar = new wxMenuBar;
m_menuBar->Append(gameMenu, "&Game");
m_menuBar->Append(editMenu, "&Edit");
m_menuBar->Append(optionsMenu, "&Options");
m_menuBar->Append(helpMenu, "&Help");
SetMenuBar(m_menuBar);
m_canvas = new FortyCanvas(this, 0, 0, 400, 400);
wxLayoutConstraints* constr = new wxLayoutConstraints;
constr->left.SameAs(this, wxLeft);
constr->top.SameAs(this, wxTop);
constr->right.SameAs(this, wxRight);
constr->height.SameAs(this, wxHeight);
m_canvas->SetConstraints(constr);
CreateStatusBar();
}
FortyFrame::~FortyFrame()
{
}
void FortyFrame::OnCloseWindow(wxCloseEvent& event)
{
if (m_canvas->OnCloseCanvas() )
{
this->Destroy();
}
else
event.Veto();
}
void
FortyFrame::NewGame(wxCommandEvent&)
{
m_canvas->NewGame();
}
void
FortyFrame::Exit(wxCommandEvent&)
{
#ifdef __WXGTK__
// wxGTK doesn't call OnClose() so we do it here
// if (OnClose())
#endif
Close(TRUE);
}
void
FortyFrame::About(wxCommandEvent&)
{
wxMessageBox(
"Forty Thieves\n\n"
"A freeware program using the wxWindows\n"
"portable C++ GUI toolkit.\n"
"http://web.ukonline.co.uk/julian.smart/wxwin\n"
"http://www.freiburg.linux.de/~wxxt\n\n"
"Author: Chris Breeze (c) 1992-1998\n"
"email: chris.breeze@iname.com",
"About Forty Thieves",
wxOK, this
);
}
void
FortyFrame::Undo(wxCommandEvent&)
{
m_canvas->Undo();
}
void
FortyFrame::Redo(wxCommandEvent&)
{
m_canvas->Redo();
}
void
FortyFrame::Scores(wxCommandEvent&)
{
m_canvas->UpdateScores();
ScoreDialog scores(this, m_canvas->GetScoreFile());
scores.Display();
}
void
FortyFrame::ToggleRightButtonUndo(wxCommandEvent& event)
{
bool checked = m_menuBar->IsChecked(event.GetId());
m_canvas->EnableRightButtonUndo(checked);
}
void
FortyFrame::ToggleHelpingHand(wxCommandEvent& event)
{
bool checked = m_menuBar->IsChecked(event.GetId());
m_canvas->EnableHelpingHand(checked);
}

8
demos/forty/forty.def Normal file
View File

@@ -0,0 +1,8 @@
NAME Forty
DESCRIPTION 'Forty Thieves'
EXETYPE WINDOWS
STUB 'WINSTUB.EXE'
CODE PRELOAD MOVEABLE DISCARDABLE
DATA PRELOAD MOVEABLE MULTIPLE
HEAPSIZE 4048
STACKSIZE 16000

31
demos/forty/forty.h Normal file
View File

@@ -0,0 +1,31 @@
/////////////////////////////////////////////////////////////////////////////
// Name: forty.h
// Purpose: Forty Thieves patience game
// Author: Chris Breeze
// Modified by:
// Created: 21/07/97
// RCS-ID: $Id$
// Copyright: (c) 1993-1998 Chris Breeze
// Licence: wxWindows licence
//---------------------------------------------------------------------------
// Last modified: 22nd July 1998 - ported to wxWindows 2.0
/////////////////////////////////////////////////////////////////////////////
#ifndef _FORTY_H_
#define _FORTY_H_
class FortyApp: public wxApp
{
public:
bool OnInit();
static const wxColour& BackgroundColour();
static const wxColour& TextColour();
static const wxBrush& BackgroundBrush();
private:
static wxColour* m_backgroundColour;
static wxColour* m_textColour;
static wxBrush* m_backgroundBrush;
};
#endif

6
demos/forty/forty.rc Normal file
View File

@@ -0,0 +1,6 @@
#include "wx/msw/wx.rc"
CardsIcon ICON "cards.ico"
CardPictures BITMAP "pictures.bmp"
CardSymbols BITMAP "symbols.bmp"

944
demos/forty/game.cpp Normal file
View File

@@ -0,0 +1,944 @@
/////////////////////////////////////////////////////////////////////////////
// Name: game.cpp
// Purpose: Forty Thieves patience game
// Author: Chris Breeze
// Modified by:
// Created: 21/07/97
// RCS-ID: $Id$
// Copyright: (c) 1993-1998 Chris Breeze
// Licence: wxWindows licence
//---------------------------------------------------------------------------
// Last modified: 22nd July 1998 - ported to wxWindows 2.0
/////////////////////////////////////////////////////////////////////////////
#ifdef __GNUG__
#pragma implementation
#pragma interface
#endif
// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <string.h>
#include "forty.h"
#include "game.h"
Game::Game(int wins, int games, int score) :
m_inPlay(FALSE),
m_moveIndex(0),
m_redoIndex(0),
m_bmap(0),
m_bmapCard(0)
{
int i;
m_pack = new Pack(2, 2 + 4 * (CardHeight + 2));
srand(time(0));
for (i = 0; i < 5; i++) m_pack->Shuffle();
m_discard = new Discard(2, 2 + 5 * (CardHeight + 2));
for (i = 0; i < 8; i++)
{
m_foundations[i] = new Foundation(2 + (i / 4) * (CardWidth + 2),
2 + (i % 4) * (CardHeight + 2));
}
for (i = 0; i < 10; i++)
{
m_bases[i] = new Base(8 + (i + 2) * (CardWidth + 2), 2);
}
Deal();
m_srcPile = 0;
m_liftedCard = 0;
// copy the input parameters for future reference
m_numWins = wins;
m_numGames = games;
m_totalScore = score;
m_currentScore = 0;
}
// Make sure we delete all objects created by the game object
Game::~Game()
{
int i;
delete m_pack;
delete m_discard;
for (i = 0; i < 8; i++)
{
delete m_foundations[i];
}
for (i = 0; i < 10; i++)
{
delete m_bases[i];
}
delete m_bmap;
delete m_bmapCard;
}
/*
Set the score for a new player.
NB: call Deal() first if the new player is to start
a new game
*/
void Game::NewPlayer(int wins, int games, int score)
{
m_numWins = wins;
m_numGames = games;
m_totalScore = score;
m_currentScore = 0;
}
// Undo the last move
void Game::Undo(wxDC& dc)
{
if (m_moveIndex > 0)
{
m_moveIndex--;
Card* card = m_moves[m_moveIndex].dest->RemoveTopCard(dc);
m_moves[m_moveIndex].src->AddCard(dc, card);
DisplayScore(dc);
}
}
// Redo the last move
void Game::Redo(wxDC& dc)
{
if (m_moveIndex < m_redoIndex)
{
Card* card = m_moves[m_moveIndex].src->RemoveTopCard(dc);
if (m_moves[m_moveIndex].src == m_pack)
{
m_pack->Redraw(dc);
card->TurnCard(faceup);
}
m_moves[m_moveIndex].dest->AddCard(dc, card);
DisplayScore(dc);
m_moveIndex++;
}
}
void Game::DoMove(wxDC& dc, Pile* src, Pile* dest)
{
if (m_moveIndex < MaxMoves)
{
if (src == dest)
{
wxMessageBox("Game::DoMove() src == dest", "Debug message",
wxOK | wxICON_EXCLAMATION);
}
m_moves[m_moveIndex].src = src;
m_moves[m_moveIndex].dest = dest;
m_moveIndex++;
// when we do a move any moves in redo buffer are discarded
m_redoIndex = m_moveIndex;
}
else
{
wxMessageBox("Game::DoMove() Undo buffer full", "Debug message",
wxOK | wxICON_EXCLAMATION);
}
if (!m_inPlay)
{
m_inPlay = TRUE;
m_numGames++;
}
DisplayScore(dc);
}
void Game::DisplayScore(wxDC& dc)
{
wxColour bgColour = FortyApp::BackgroundColour();
wxPen* pen = wxThePenList->FindOrCreatePen(bgColour, 1, wxSOLID);
dc.SetTextBackground(bgColour);
dc.SetTextForeground(FortyApp::TextColour());
dc.SetBrush(FortyApp::BackgroundBrush());
dc.SetPen(* pen);
// count the number of cards in foundations
m_currentScore = 0;
for (int i = 0; i < 8; i++)
{
m_currentScore += m_foundations[i]->GetNumCards();
}
int x, y;
m_pack->GetTopCardPos(x, y);
x += 12 * CardWidth - 105;
int w, h;
{
long width, height;
dc.GetTextExtent("Average score:m_x", &width, &height);
w = width;
h = height;
}
dc.DrawRectangle(x + w, y, 20, 4 * h);
char str[80];
sprintf(str, "%d", m_currentScore);
dc.DrawText("Score:", x, y);
dc.DrawText(str, x + w, y);
y += h;
sprintf(str, "%d", m_numGames);
dc.DrawText("Games played:", x, y);
dc.DrawText(str, x + w, y);
y += h;
sprintf(str, "%d", m_numWins);
dc.DrawText("Games won:", x, y);
dc.DrawText(str, x + w, y);
y += h;
int average = 0;
if (m_numGames > 0)
{
average = (2 * (m_currentScore + m_totalScore) + m_numGames ) / (2 * m_numGames);
}
sprintf(str, "%d", average);
dc.DrawText("Average score:", x, y);
dc.DrawText(str, x + w, y);
}
// Shuffle the m_pack and deal the cards
void Game::Deal()
{
int i, j;
Card* card;
// Reset all the piles, the undo buffer and shuffle the m_pack
m_moveIndex = 0;
m_pack->ResetPile();
for (i = 0; i < 5; i++)
{
m_pack->Shuffle();
}
m_discard->ResetPile();
for (i = 0; i < 10; i++)
{
m_bases[i]->ResetPile();
}
for (i = 0; i < 8; i++)
{
m_foundations[i]->ResetPile();
}
// Deal the initial 40 cards onto the bases
for (i = 0; i < 10; i++)
{
for (j = 1; j <= 4; j++)
{
card = m_pack->RemoveTopCard();
card->TurnCard(faceup);
m_bases[i]->AddCard(card);
}
}
if (m_inPlay)
{
// player has started the game and then redealt
// and so we must add the score for this game to the total score
m_totalScore += m_currentScore;
}
m_currentScore = 0;
m_inPlay = FALSE;
}
// Redraw the m_pack, discard pile, the bases and the foundations
void Game::Redraw(wxDC& dc)
{
int i;
m_pack->Redraw(dc);
m_discard->Redraw(dc);
for (i = 0; i < 8; i++)
{
m_foundations[i]->Redraw(dc);
}
for (i = 0; i < 10; i++)
{
m_bases[i]->Redraw(dc);
}
DisplayScore(dc);
if (m_bmap == 0)
{
m_bmap = new wxBitmap(CardWidth, CardHeight);
m_bmapCard = new wxBitmap(CardWidth, CardHeight);
// Initialise the card bitmap to the background colour
wxMemoryDC memoryDC;
memoryDC.SelectObject(*m_bmapCard);
memoryDC.SetBrush(FortyApp::BackgroundBrush());
memoryDC.DrawRectangle(0, 0, CardWidth, CardHeight);
memoryDC.SelectObject(*m_bmap);
memoryDC.DrawRectangle(0, 0, CardWidth, CardHeight);
memoryDC.SelectObject(wxNullBitmap);
}
}
// Test to see if the point (x, y) is over the top card of one of the piles
// Returns pointer to the pile, or 0 if (x, y) is not over a pile
// or the pile is empty
Pile* Game::WhichPile(int x, int y)
{
if (m_pack->GetCard(x, y) &&
m_pack->GetCard(x, y) == m_pack->GetTopCard())
{
return m_pack;
}
if (m_discard->GetCard(x, y) &&
m_discard->GetCard(x, y) == m_discard->GetTopCard())
{
return m_discard;
}
int i;
for (i = 0; i < 8; i++)
{
if (m_foundations[i]->GetCard(x, y) &&
m_foundations[i]->GetCard(x, y) == m_foundations[i]->GetTopCard())
{
return m_foundations[i];
}
}
for (i = 0; i < 10; i++)
{
if (m_bases[i]->GetCard(x, y) &&
m_bases[i]->GetCard(x, y) == m_bases[i]->GetTopCard())
{
return m_bases[i];
}
}
return 0;
}
// Left button is pressed - if cursor is over the m_pack then deal a card
// otherwise if it is over a card pick it up ready to be dragged - see MouseMove()
bool Game::LButtonDown(wxDC& dc, int x, int y)
{
m_srcPile = WhichPile(x, y);
if (m_srcPile == m_pack)
{
Card* card = m_pack->RemoveTopCard();
if (card)
{
m_pack->Redraw(dc);
card->TurnCard(faceup);
m_discard->AddCard(dc, card);
DoMove(dc, m_pack, m_discard);
}
m_srcPile = 0;
}
else if (m_srcPile)
{
m_srcPile->GetTopCardPos(m_xPos, m_yPos);
m_xOffset = m_xPos - x;
m_yOffset = m_yPos - y;
// Copy the area under the card
// Initialise the card bitmap to the background colour
{
wxMemoryDC memoryDC;
memoryDC.SelectObject(*m_bmap);
m_liftedCard = m_srcPile->RemoveTopCard(memoryDC, m_xPos, m_yPos);
}
// Draw the card in card bitmap ready for blitting onto
// the screen
{
wxMemoryDC memoryDC;
memoryDC.SelectObject(*m_bmapCard);
m_liftedCard->Draw(memoryDC, 0, 0);
}
}
return m_srcPile != 0;
}
// Called when the left button is double clicked
// If a card is under the pointer and it can move elsewhere then move it.
// Move onto a foundation as first choice, a populated base as second and
// an empty base as third choice.
// NB Cards in the m_pack cannot be moved in this way - they aren't in play
// yet
void Game::LButtonDblClk(wxDC& dc, int x, int y)
{
Pile* pile = WhichPile(x, y);
if (!pile) return;
// Double click on m_pack is the same as left button down
if (pile == m_pack)
{
LButtonDown(dc, x, y);
}
else
{
Card* card = pile->GetTopCard();
if (card)
{
int i;
// if the card is an ace then try to place it next
// to an ace of the same suit
if (card->GetPipValue() == 1)
{
for(i = 0; i < 4; i++)
{
Card* m_topCard;
if ((m_topCard = m_foundations[i]->GetTopCard()))
{
if (m_topCard->GetSuit() == card->GetSuit() &&
m_foundations[i + 4] != pile &&
m_foundations[i + 4]->GetTopCard() == 0)
{
pile->RemoveTopCard(dc);
m_foundations[i + 4]->AddCard(dc, card);
DoMove(dc, pile, m_foundations[i + 4]);
return;
}
}
}
}
// try to place the card on a foundation
for(i = 0; i < 8; i++)
{
if (m_foundations[i]->AcceptCard(card) && m_foundations[i] != pile)
{
pile->RemoveTopCard(dc);
m_foundations[i]->AddCard(dc, card);
DoMove(dc, pile, m_foundations[i]);
return;
}
}
// try to place the card on a populated base
for(i = 0; i < 10; i++)
{
if (m_bases[i]->AcceptCard(card) &&
m_bases[i] != pile &&
m_bases[i]->GetTopCard())
{
pile->RemoveTopCard(dc);
m_bases[i]->AddCard(dc, card);
DoMove(dc, pile, m_bases[i]);
return;
}
}
// try to place the card on any base
for(i = 0; i < 10; i++)
{
if (m_bases[i]->AcceptCard(card) && m_bases[i] != pile)
{
pile->RemoveTopCard(dc);
m_bases[i]->AddCard(dc, card);
DoMove(dc, pile, m_bases[i]);
return;
}
}
}
}
}
// Test to see whether the game has been won:
// i.e. m_pack, discard and bases are empty
bool Game::HaveYouWon()
{
if (m_pack->GetTopCard()) return FALSE;
if (m_discard->GetTopCard()) return FALSE;
for(int i = 0; i < 10; i++)
{
if (m_bases[i]->GetTopCard()) return FALSE;
}
m_numWins++;
m_totalScore += m_currentScore;
m_currentScore = 0;
return TRUE;
}
// See whether the card under the cursor can be moved somewhere else
// Returns TRUE if it can be moved, FALSE otherwise
bool Game::CanYouGo(int x, int y)
{
Pile* pile = WhichPile(x, y);
if (pile && pile != m_pack)
{
Card* card = pile->GetTopCard();
if (card)
{
int i;
for(i = 0; i < 8; i++)
{
if (m_foundations[i]->AcceptCard(card) && m_foundations[i] != pile)
{
return TRUE;
}
}
for(i = 0; i < 10; i++)
{
if (m_bases[i]->GetTopCard() &&
m_bases[i]->AcceptCard(card) &&
m_bases[i] != pile)
{
return TRUE;
}
}
}
}
return FALSE;
}
// Called when the left button is released after dragging a card
// Scan the piles to see if this card overlaps a pile and can be added
// to the pile. If the card overlaps more than one pile on which it can be placed
// then put it on the nearest pile.
void Game::LButtonUp(wxDC& dc, int x, int y)
{
if (m_srcPile)
{
// work out the position of the dragged card
x += m_xOffset;
y += m_yOffset;
Pile* nearestPile = 0;
int distance = (CardHeight + CardWidth) * (CardHeight + CardWidth);
// find the nearest pile which will accept the card
int i;
for (i = 0; i < 8; i++)
{
if (DropCard(x, y, m_foundations[i], m_liftedCard))
{
if (m_foundations[i]->CalcDistance(x, y) < distance)
{
nearestPile = m_foundations[i];
distance = nearestPile->CalcDistance(x, y);
}
}
}
for (i = 0; i < 10; i++)
{
if (DropCard(x, y, m_bases[i], m_liftedCard))
{
if (m_bases[i]->CalcDistance(x, y) < distance)
{
nearestPile = m_bases[i];
distance = nearestPile->CalcDistance(x, y);
}
}
}
// Restore the area under the card
wxMemoryDC memoryDC;
memoryDC.SelectObject(*m_bmap);
dc.Blit(m_xPos, m_yPos, CardWidth, CardHeight,
&memoryDC, 0, 0, wxCOPY);
// Draw the card in its new position
if (nearestPile)
{
// Add to new pile
nearestPile->AddCard(dc, m_liftedCard);
if (nearestPile != m_srcPile)
{
DoMove(dc, m_srcPile, nearestPile);
}
}
else
{
// Return card to src pile
m_srcPile->AddCard(dc, m_liftedCard);
}
m_srcPile = 0;
m_liftedCard = 0;
}
}
bool Game::DropCard(int x, int y, Pile* pile, Card* card)
{
bool retval = FALSE;
if (pile->Overlap(x, y))
{
if (pile->AcceptCard(card))
{
retval = TRUE;
}
}
return retval;
}
void Game::MouseMove(wxDC& dc, int mx, int my)
{
if (m_liftedCard)
{
wxMemoryDC memoryDC;
memoryDC.SelectObject(*m_bmap);
int dx = mx + m_xOffset - m_xPos;
int dy = my + m_yOffset - m_yPos;
if (abs(dx) >= CardWidth || abs(dy) >= CardHeight)
{
// Restore the area under the card
dc.Blit(m_xPos, m_yPos, CardWidth, CardHeight,
&memoryDC, 0, 0, wxCOPY);
// Copy the area under the card in the new position
memoryDC.Blit(0, 0, CardWidth, CardHeight,
&dc, m_xPos + dx, m_yPos + dy, wxCOPY);
}
else if (dx >= 0)
{
// dx >= 0
dc.Blit(m_xPos, m_yPos, dx, CardHeight, &memoryDC, 0, 0, wxCOPY);
if (dy >= 0)
{
// dy >= 0
dc.Blit(m_xPos + dx, m_yPos, CardWidth - dx, dy, &memoryDC, dx, 0, wxCOPY);
memoryDC.Blit(0, 0, CardWidth - dx, CardHeight - dy,
&memoryDC, dx, dy, wxCOPY);
memoryDC.Blit(0, CardHeight - dy, CardWidth - dx, dy,
&dc, m_xPos + dx, m_yPos + CardHeight, wxCOPY);
}
else
{
// dy < 0
dc.Blit(m_xPos + dx, m_yPos + dy + CardHeight, CardWidth - dx, -dy,
&memoryDC, dx, CardHeight + dy, wxCOPY);
memoryDC.Blit(0, -dy, CardWidth - dx, CardHeight + dy,
&memoryDC, dx, 0, wxCOPY);
memoryDC.Blit(0, 0, CardWidth - dx, -dy,
&dc, m_xPos + dx, m_yPos + dy, wxCOPY);
}
memoryDC.Blit(CardWidth - dx, 0, dx, CardHeight,
&dc, m_xPos + CardWidth, m_yPos + dy, wxCOPY);
}
else
{
// dx < 0
dc.Blit(m_xPos + CardWidth + dx, m_yPos, -dx, CardHeight,
&memoryDC, CardWidth + dx, 0, wxCOPY);
if (dy >= 0)
{
dc.Blit(m_xPos, m_yPos, CardWidth + dx, dy, &memoryDC, 0, 0, wxCOPY);
memoryDC.Blit(-dx, 0, CardWidth + dx, CardHeight - dy,
&memoryDC, 0, dy, wxCOPY);
memoryDC.Blit(-dx, CardHeight - dy, CardWidth + dx, dy,
&dc, m_xPos, m_yPos + CardHeight, wxCOPY);
}
else
{
// dy < 0
dc.Blit(m_xPos, m_yPos + CardHeight + dy, CardWidth + dx, -dy,
&memoryDC, 0, CardHeight + dy, wxCOPY);
memoryDC.Blit(-dx, -dy, CardWidth + dx, CardHeight + dy,
&memoryDC, 0, 0, wxCOPY);
memoryDC.Blit(-dx, 0, CardWidth + dx, -dy,
&dc, m_xPos, m_yPos + dy, wxCOPY);
}
memoryDC.Blit(0, 0, -dx, CardHeight,
&dc, m_xPos + dx, m_yPos + dy, wxCOPY);
}
m_xPos += dx;
m_yPos += dy;
// draw the card in its new position
memoryDC.SelectObject(*m_bmapCard);
dc.Blit(m_xPos, m_yPos, CardWidth, CardHeight,
&memoryDC, 0, 0, wxCOPY);
}
}
//----------------------------------------------//
// The Pack class: holds the two decks of cards //
//----------------------------------------------//
Pack::Pack(int x, int y) : Pile(x, y, 0, 0)
{
for (m_topCard = 0; m_topCard < NumCards; m_topCard++)
{
m_cards[m_topCard] = new Card(1 + m_topCard / 2, facedown);
}
m_topCard = NumCards - 1;
}
void Pack::Shuffle()
{
Card* temp[NumCards];
int i;
// Don't try to shuffle an empty m_pack!
if (m_topCard < 0) return;
// Copy the cards into a temporary array. Start by clearing
// the array and then copy the card into a random position.
// If the position is occupied then find the next lower position.
for (i = 0; i <= m_topCard; i++)
{
temp[i] = 0;
}
for (i = 0; i <= m_topCard; i++)
{
int pos = rand() % (m_topCard + 1);
while (temp[pos])
{
pos--;
if (pos < 0) pos = m_topCard;
}
m_cards[i]->TurnCard(facedown);
temp[pos] = m_cards[i];
m_cards[i] = 0;
}
// Copy each card back into the m_pack in a random
// position. If position is occupied then find nearest
// unoccupied position after the random position.
for (i = 0; i <= m_topCard; i++)
{
int pos = rand() % (m_topCard + 1);
while (m_cards[pos])
{
pos++;
if (pos > m_topCard) pos = 0;
}
m_cards[pos] = temp[i];
}
}
void Pack::Redraw(wxDC& dc)
{
Pile::Redraw(dc);
char str[10];
sprintf(str, "%d ", m_topCard + 1);
dc.SetTextBackground(FortyApp::BackgroundColour());
dc.SetTextForeground(FortyApp::TextColour());
dc.DrawText(str, m_x + CardWidth + 5, m_y + CardHeight / 2);
}
void Pack::AddCard(Card* card)
{
if (card == m_cards[m_topCard + 1])
{
m_topCard++;
}
else
{
wxMessageBox("Pack::AddCard() Undo error", "Forty Thieves: Warning",
wxOK | wxICON_EXCLAMATION);
}
card->TurnCard(facedown);
}
Pack::~Pack()
{
for (m_topCard = 0; m_topCard < NumCards; m_topCard++)
{
delete m_cards[m_topCard];
}
};
//------------------------------------------------------//
// The Base class: holds the initial pile of four cards //
//------------------------------------------------------//
Base::Base(int x, int y) : Pile(x, y, 0, 12)
{
m_topCard = -1;
}
bool Base::AcceptCard(Card* card)
{
bool retval = FALSE;
if (m_topCard >= 0)
{
if (m_cards[m_topCard]->GetSuit() == card->GetSuit() &&
m_cards[m_topCard]->GetPipValue() - 1 == card->GetPipValue())
{
retval = TRUE;
}
}
else
{
// pile is empty - ACCEPT
retval = TRUE;
}
return retval;
}
Base::~Base()
{
// nothing special at the moment
};
//----------------------------------------------------------------//
// The Foundation class: holds the cards built up from the ace... //
//----------------------------------------------------------------//
Foundation::Foundation(int x, int y) : Pile(x, y, 0, 0)
{
m_topCard = -1;
}
bool Foundation::AcceptCard(Card* card)
{
bool retval = FALSE;
if (m_topCard >= 0)
{
if (m_cards[m_topCard]->GetSuit() == card->GetSuit() &&
m_cards[m_topCard]->GetPipValue() + 1 == card->GetPipValue())
{
retval = TRUE;
}
}
else if (card->GetPipValue() == 1)
{
// It's an ace and the pile is empty - ACCEPT
retval = TRUE;
}
return retval;
}
Foundation::~Foundation()
{
// nothing special at the moment
};
//----------------------------------------------------//
// The Discard class: holds cards dealt from the m_pack //
//----------------------------------------------------//
Discard::Discard(int x, int y) : Pile(x, y, 19, 0)
{
m_topCard = -1;
}
void Discard::Redraw(wxDC& dc)
{
if (m_topCard >= 0)
{
if (m_dx == 0 && m_dy == 0)
{
m_cards[m_topCard]->Draw(dc, m_x, m_y);
}
else
{
int x = m_x;
int y = m_y;
for (int i = 0; i <= m_topCard; i++)
{
m_cards[i]->Draw(dc, x, y);
x += m_dx;
y += m_dy;
if (i == 31)
{
x = m_x;
y = m_y + CardHeight / 3;
}
}
}
}
else
{
Card::DrawNullCard(dc, m_x, m_y);
}
}
void Discard::GetTopCardPos(int& x, int& y)
{
if (m_topCard < 0)
{
x = m_x;
y = m_y;
}
else if (m_topCard > 31)
{
x = m_x + m_dx * (m_topCard - 32);
y = m_y + CardHeight / 3;
}
else
{
x = m_x + m_dx * m_topCard;
y = m_y;
}
}
Card* Discard::RemoveTopCard(wxDC& dc, int m_xOffset, int m_yOffset)
{
Card* card;
if (m_topCard <= 31)
{
card = Pile::RemoveTopCard(dc, m_xOffset, m_yOffset);
}
else
{
int topX, topY, x, y;
GetTopCardPos(topX, topY);
card = Pile::RemoveTopCard();
card->Erase(dc, topX - m_xOffset, topY - m_yOffset);
GetTopCardPos(x, y);
dc.SetClippingRegion(topX - m_xOffset, topY - m_yOffset,
CardWidth, CardHeight);
for (int i = m_topCard - 31; i <= m_topCard - 31 + CardWidth / m_dx; i++)
{
m_cards[i]->Draw(dc, m_x - m_xOffset + i * m_dx, m_y - m_yOffset);
}
if (m_topCard > 31)
{
m_cards[m_topCard]->Draw(dc, topX - m_xOffset - m_dx, topY - m_yOffset);
}
dc.DestroyClippingRegion();
}
return card;
}
Discard::~Discard()
{
// nothing special at the moment
};

135
demos/forty/game.h Normal file
View File

@@ -0,0 +1,135 @@
/////////////////////////////////////////////////////////////////////////////
// Name: game.h
// Purpose: Forty Thieves patience game
// Author: Chris Breeze
// Modified by:
// Created: 21/07/97
// RCS-ID: $Id$
// Copyright: (c) 1993-1998 Chris Breeze
// Licence: wxWindows licence
//---------------------------------------------------------------------------
// Last modified: 22nd July 1998 - ported to wxWindows 2.0
/////////////////////////////////////////////////////////////////////////////
#ifndef _GAME_H_
#define _GAME_H_
#include "card.h"
#include "pile.h"
const int MaxMoves = 800;
//---------------------------------------//
// A class which holds the pack of cards //
//---------------------------------------//
class Pack : public Pile {
public:
Pack(int x, int y);
~Pack();
void Redraw(wxDC& dc);
void ResetPile() { m_topCard = NumCards - 1; }
void Shuffle();
void AddCard(Card* card); // Add card
void AddCard(wxDC& dc, Card* card) { AddCard(card); Redraw(dc); }
};
//----------------------------------------------------------//
// A class which holds a base i.e. the initial 10 x 4 cards //
//----------------------------------------------------------//
class Base : public Pile {
public:
Base(int x, int y);
~Base();
bool AcceptCard(Card* card);
};
//----------------------------------------------------//
// A class which holds a foundation i.e. Ace, 2, 3... //
//----------------------------------------------------//
class Foundation : public Pile {
public:
Foundation(int x, int y);
~Foundation();
bool AcceptCard(Card* card);
};
//--------------------------------------//
// A class which holds the discard pile //
//--------------------------------------//
class Discard : public Pile {
public:
Discard(int x, int y);
~Discard();
void Redraw(wxDC& dc);
void GetTopCardPos(int& x, int& y);
Card* RemoveTopCard(wxDC& dc, int m_xOffset, int m_yOffset);
};
class Game {
public:
Game(int wins, int games, int score);
virtual ~Game();
void NewPlayer(int wins, int games, int score);
void Deal(); // Shuffle and deal a new game
bool CanYouGo(int x, int y); // can card under (x,y) go somewhere?
bool HaveYouWon(); // have you won the game?
void Undo(wxDC& dc); // Undo the last go
void Redo(wxDC& dc); // Redo the last go
void Redraw(wxDC& dc);
void DisplayScore(wxDC& dc);
bool LButtonDown(wxDC& dc, int mx, int my); //
void LButtonUp(wxDC& dc, int mx, int my);
void LButtonDblClk(wxDC& dc, int mx, int my);
void MouseMove(wxDC& dc, int mx, int my);
int GetNumWins() const { return m_numWins; }
int GetNumGames() const { return m_numGames; }
int GetScore() const { return m_currentScore + m_totalScore; }
bool InPlay() const { return m_inPlay; }
private:
bool DropCard(int x, int y, Pile* pile, Card* card);
// can the card at (x, y) be dropped on the pile?
Pile* WhichPile(int x, int y); // which pile is (x, y) over?
void DoMove(wxDC& dc, Pile* src, Pile* dest);
bool m_inPlay; // flag indicating that the game has started
// undo buffer
struct {
Pile* src;
Pile* dest;
} m_moves[MaxMoves];
int m_moveIndex; // current position in undo/redo buffer
int m_redoIndex; // max move index available for redo
// the various piles of cards
Pack* m_pack;
Discard* m_discard;
Base* m_bases[10];
Foundation* m_foundations[8];
// variables to do with dragging cards
Pile* m_srcPile;
Card* m_liftedCard;
int m_xPos, m_yPos; // current coords of card being dragged
int m_xOffset, m_yOffset; // card/mouse offset when dragging a card
wxBitmap* m_bmap;
wxBitmap* m_bmapCard;
// variables to do with scoring
int m_numGames;
int m_numWins;
int m_totalScore;
int m_currentScore;
};
#endif // _GAME_H_

BIN
demos/forty/make_cw.mcp Normal file

Binary file not shown.

16
demos/forty/makefile.b32 Normal file
View File

@@ -0,0 +1,16 @@
#
# File: makefile.b32
# Author: Julian Smart
# Created: 1999
# Updated:
# Copyright:
#
# Makefile : Builds sample for 32-bit BC++
WXDIR = $(WXWIN)
TARGET=forty
OBJECTS = $(TARGET).obj canvas.obj card.obj game.obj pile.obj playerdg.obj scoredg.obj scorefil.obj
!include $(WXDIR)\src\makeprog.b32

19
demos/forty/makefile.bcc Normal file
View File

@@ -0,0 +1,19 @@
#
# File: makefile.bcc
# Author: Julian Smart
# Created: 1998
# Updated:
#
# Builds a BC++ 16-bit sample
!if "$(WXWIN)" == ""
!error You must define the WXWIN variable in autoexec.bat, e.g. WXWIN=c:\wx
!endif
WXDIR = $(WXWIN)
TARGET=forty
OBJECTS=$(TARGET).obj canvas.obj card.obj game.obj pile.obj playerdg.obj scoredg.obj scorefil.obj
!include $(WXDIR)\src\makeprog.bcc

17
demos/forty/makefile.dos Normal file
View File

@@ -0,0 +1,17 @@
#
# File: makefile.dos
# Author: Julian Smart
# Created: 1998
# Updated:
#
# Makefile : Builds 16-bit sample, VC++ 1.5
# Use FINAL=1 argument to nmake to build final version with no debugging
# info
WXDIR = $(WXWIN)
TARGET=forty
OBJECTS = $(TARGET).obj canvas.obj card.obj game.obj pile.obj playerdg.obj scoredg.obj scorefil.obj
!include $(WXDIR)\src\makeprog.msc

16
demos/forty/makefile.g95 Normal file
View File

@@ -0,0 +1,16 @@
#
# File: makefile.g95
# Author: Julian Smart
# Created: 1999
# Updated:
# Copyright: (c) Julian Smart, 1999
#
# Makefile for wxWindows sample (Cygwin/Mingw32).
WXDIR = ../..
TARGET=forty
OBJECTS = $(TARGET).o canvas.o card.o game.o pile.o playerdg.o scoredg.o scorefil.o
include $(WXDIR)/src/makeprog.g95

35
demos/forty/makefile.unx Normal file
View File

@@ -0,0 +1,35 @@
#
# File: Makefile for samples
# Author: Robert Roebling
# Created: 1999
# Updated:
# Copyright: (c) 1998 Robert Roebling
#
# This makefile requires a Unix version of wxWindows
# to be installed on your system. This is most often
# done typing "make install" when using the complete
# sources of wxWindows or by installing the two
# RPM packages wxGTK.XXX.rpm and wxGTK-devel.XXX.rpm
# under Linux.
#
CC = g++
PROGRAM = forty
OBJECTS = $(PROGRAM).o canvas.o card.o game.o pile.o playerdg.o scoredg.o scorefil.o
# implementation
.SUFFIXES: .o .cpp
.cpp.o :
$(CC) -c `wx-config --cflags` -o $@ $<
all: $(PROGRAM)
$(PROGRAM): $(OBJECTS)
$(CC) -o $(PROGRAM) $(OBJECTS) `wx-config --libs`
clean:
rm -f *.o $(PROGRAM)

18
demos/forty/makefile.vc Normal file
View File

@@ -0,0 +1,18 @@
#
# File: makefile.vc
# Author: Julian Smart
# Created: 1999
# Updated:
# Copyright: (c) Julian Smart
#
# Makefile : Builds sample (VC++, WIN32)
# Use FINAL=1 argument to nmake to build final version with no debug info.
# Set WXDIR for your system
WXDIR = $(WXWIN)
PROGRAM=forty
OBJECTS = $(PROGRAM).obj card.obj canvas.obj game.obj pile.obj playerdg.obj scoredg.obj scorefil.obj
!include $(WXDIR)\src\makeprog.vc

15
demos/forty/makefile.wat Normal file
View File

@@ -0,0 +1,15 @@
#
# Makefile for WATCOM
#
# Created by Julian Smart, January 1999
#
#
WXDIR = $(%WXWIN)
PROGRAM = forty
OBJECTS = $(PROGRAM).obj canvas.obj card.obj game.obj pile.obj playerdg.obj scoredg.obj scorefil.obj
!include $(WXDIR)\src\makeprog.wat

BIN
demos/forty/pictures.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

60
demos/forty/pictures.xpm Normal file
View File

@@ -0,0 +1,60 @@
/* XPM */
static char *Pictures[] = {
/* width height num_colors chars_per_pixel */
" 120 45 8 1",
/* colors */
". c #000000",
"# c #c0c0c0",
"a c #808080",
"b c #ff0000",
"c c #ffff00",
"d c #0000ff",
"e c #00ffff",
"f c #ffffff",
/* pixels */
"........................................................................................................................",
".fff.fffffff.bb.bb.bb.b.fffffffffffffff..fffffffffff..f..bbc.cc..ffffffffffffff..fff.ffffff.bbccccbcccccbb.ffffffffffff.",
".ff.c.fffffff.bbbbbbbb.ffffffffffffffff..fff.ffffff..f.ff.bbc..c.ffffffffffffff..ff.a.ffffff.bbccbbbcccbb.fffffffffffff.",
".f.cbc.fffffff........fffffffffffffffff..ff.b.fffff.f.ffff.bb..c..fffffffffffff..f.#af.ffffff.bbbbbbbbbb.ffffffffffffff.",
".f.cbc.ffffff.fff.c.c.fffffffffffffffff..ff.b.fffff..f.ff.f.bbc.c.fffffffffffff..f.#af.ffffff............ffffffffffffff.",
".ff.c.fffffff.f..f.c.c.ffffffffffffffff..fff.ffffff.f..ff..f.bb..ffffffffffffff..f.#af.ffffff.a..f.fff.f.ffffffffffffff.",
".f.cbc.ffffff.f.ff.c.c.ffffffffffffffff..ff.c.fffff.fff.ffff..b.fffffffffffffff..f.#af.ffffff.a.f..fff..f.fffffffffffff.",
".f.cbc.fffff.fffff.c.c.ffffffffffffffff..ff.c.fffff.fff.ffff....fffffffffffffff..f.#af.ffffff.a.ffff.ffff.fffffffffffff.",
".ff.c.fffff.ffffff.c.c.ffffffffffffffff..ff.c.fffff.fff..fff.b..fffffffffffffff..f.#af.ffffff.a.fffff.fff.fffffffffffff.",
".f.cbc.ffff..###ff.c.c.ffffffffffffffff..ff.c.fffff.ffffffff..b.fffffffffffffff..f.#af.ffffff.a.ffff..fff.fffffffffffff.",
".f.cbc.ffffff...ff.c.c.ffffffffffffffff..fff.ffffff.ffbbbbff.f...ffffffffffffff..f.#af.fff..f.a..ffffffff.fffffffffffff.",
".ff....ffffff.ffff.c.c.ffffffffffffffff..ff....fffff.ffffff.f.f...fffffffffffff..f.#af.fff....a...f....f..fffffffffffff.",
".f.ffff.fffff.fffff.c.c.fffffffffffffff..f.ffff.ffff..ffff.f.f.f..fffffffffffff..f.#af.ffff.aaa.a..f.f.f...ffffffffffff.",
".f....ff.f.................ffffffffffff..f....ff.f.................ffffffffffff..f.#af.fff...................ffffffffff.",
".ff.fff....eddddddddddddddd.....fffffff..f.fffff...ffffffffff.cdbb......fffffff..f.#af.....c.cc..bbbbbb..c......fffffff.",
".ff....bbbd.dbcbbbbbbbbbcbdedbbb....fff..f....f.bc.fdddddddf.cdbb.d..f.....ffff..f.#af..cbbcc.cc..bbbb..c......b....fff.",
"...bbbb...deedbbcbbcbbcbbbd.dbb.bbbb.....f.fff.fbbc.fffffff.cdbb.d..f..dd.c..ff..........cbbcc.cc......c.....bbbdfff....",
".bb....c.ccdeedbbbcccbbbbdedbb.bbb..cc...ff...c.fbbc.fdddf.cdbb.d..f..dd.cccd.f...ffff...dcbbcc.cc....cc...ddbbbdfddddf.",
"...cc.c....bd.dbcbbcbbcbbd.db.bb..cbc.b..ff.dccc.bbc.ffff.cdbb.dd..ff...cdcdfd.........f.dcbbacc.cccccc..fdcbdbbdffddff.",
"..c....bbbbbdeddddddddddddedbb..cccc.bb..f..fdcdc.bbc.ff.cdbb.dddd..ff.cccdffdc...ffff.f.dcbbcacc.c...c.fdccccdbdffddff.",
"...bb.bb....bbbbbbbbbbbbbbbb..ccbbc.bb....ffdfdccc.bbc..cdbb..........cccdfdfbc........f.dcbbccacc.ccb.fdddbdbdbddffffd.",
".bbb.b..ccc.d.d.d.d.dd.d.d.d.cccbb.bb.b..cbdfffdccc.fdfdfdfdfdfdfdfd.cccdfffbbc...ffff.f.dcbbacca.bcdcc.caddddcddff..ff.",
".bb.bb.ccbcd.d.d.d.ff.d.d.d.dcbcc.bb.bb..cbbddddcdc.dbdbdbdbdbdbdbdb.cdcddddbbc.........ddcddaacc.cdddc.ccaddcdd........",
".b.bb.bbccc.d.d.d.dd.d.d.d.d.ccc.bb.bbb..cbbfffdccc.fdfdfdfdfdfdfdfd.cccdfffdbc..ff..ffddcddddaac.ccdcb.accbbcd.f.ffff..",
"..bb.cbbcc..bbbbbbbbbbbbbbbb....b..bb....cbfdfdccc..........bbdc..cbb.cccdfdff...dffffddcdbdbddaac.bcc.ccacbbcd.f.......",
".bb.cccc..bbdeddddddddddddedbbbbb....c...cdffdccc.ff..dddd.bbdc.ff.cbb.cdcdff.f..ffddffdbdccccdfa.c...c.ccabbcd.f.ffff..",
".b.cbc..bb.bd.dbbcbbcbbcbd.db....c.cc.....dfdcdc...ff..dd.bbdc.ffff.cbb.cccd.ff..ffddffdbbdbcdff..cccccc.ccbbcd.f.......",
"..cc..bbb.bbdedbbbbcccbbbdeedcc.c....bb..f.dccc.dd..f..d.bbdc.fdddf.cbbf.c...ff..fddddfdbbbddf...cc....cc.cbbcd...ffff..",
"....bbbb.bbd.dbbbcbbcbbcbbdeed...bbbb....ff..c.dd..f..d.bbdc.fffffff.cbbf.fff.f.....fffdbbb......c......cc.cbbc.........",
".fff....bbbdedbcbbbbbbbbbcbd.dbbb....ff..ffff.....f..d.bbdc.fdddddddf.cb.f....f..fff....bb......c..bbbb..cc.cbbc..fa#.f.",
".fffffff.....ddddddddddddddde....fff.ff..fffffff......bbdc.ffffffffff...fffff.f..fffffff.......c..bbbbbb..cc......fa#.f.",
".ffffffffffff.................f.ff....f..ffffffffffff.................f.ff....f..ffffffffff...................fff.fa#.f.",
".fffffffffffffff.c.c.fffff.fffff.ffff.f..fffffffffffff..f.f.f.ffff..ffff.ffff.f..ffffffffffff...f.f.f..a.aaa.ffff.fa#.f.",
".ffffffffffffffff.c.c.ffff.ffffff....ff..fffffffffffff...f.f.ffffff.fffff....ff..fffffffffffff..f....f...a....fff.fa#.f.",
".ffffffffffffffff.c.c.ff...ffffff.cbc.f..ffffffffffffff...f.ffbbbbff.ffffff.fff..fffffffffffff.ffffffff..a.f..fff.fa#.f.",
".ffffffffffffffff.c.c.ff###..ffff.cbc.f..fffffffffffffff.b..ffffffff.fffff.c.ff..fffffffffffff.fff..ffff.a.ffffff.fa#.f.",
".ffffffffffffffff.c.c.ffffff.fffff.c.ff..fffffffffffffff..b.fff..fff.fffff.c.ff..fffffffffffff.fff.fffff.a.ffffff.fa#.f.",
".ffffffffffffffff.c.c.fffff.fffff.cbc.f..fffffffffffffff....ffff.fff.fffff.c.ff..fffffffffffff.ffff.ffff.a.ffffff.fa#.f.",
".ffffffffffffffff.c.c.ff.f.ffffff.cbc.f..fffffffffffffff.b..ffff.fff.fffff.c.ff..fffffffffffff.f..fff..f.a.ffffff.fa#.f.",
".ffffffffffffffff.c.c.f..f.fffffff.c.ff..ffffffffffffff..bb.f..ff..f.ffffff.fff..ffffffffffffff.f.fff.ff.a.ffffff.fa#.f.",
".fffffffffffffffff.c.c.fff.ffffff.cbc.f..fffffffffffff.c.cbb.f.ff.f..fffff.b.ff..ffffffffffffff............ffffff.fa#.f.",
".fffffffffffffffff........fffffff.cbc.f..fffffffffffff..c..bb.ffff.f.fffff.b.ff..ffffffffffffff.bbbbbbbbbb.ffffff.fa#.f.",
".ffffffffffffffff.bbbbbbbb.fffffff.c.ff..ffffffffffffff.c..cbb.ff.f..ffffff.fff..fffffffffffff.bbcccbbbccbb.ffffff.a.ff.",
".fffffffffffffff.b.bb.bb.bb.fffffff.fff..ffffffffffffff..cc.cbb..f..fffffffffff..ffffffffffff.bbcccccbccccbb.ffffff.fff.",
"........................................................................................................................"
};

305
demos/forty/pile.cpp Normal file
View File

@@ -0,0 +1,305 @@
/////////////////////////////////////////////////////////////////////////////
// Name: pile.cpp
// Purpose: Forty Thieves patience game
// Author: Chris Breeze
// Modified by:
// Created: 21/07/97
// RCS-ID: $Id$
// Copyright: (c) 1993-1998 Chris Breeze
// Licence: wxWindows licence
//---------------------------------------------------------------------------
// Last modified: 22nd July 1998 - ported to wxWindows 2.0
/////////////////////////////////////////////////////////////////////////////
//+-------------------------------------------------------------+
//| Description: |
//| The base class for holding piles of playing cards. |
//+-------------------------------------------------------------+
#ifdef __GNUG__
#pragma implementation
#pragma interface
#endif
// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
#ifdef __GNUG__
#pragma implementation
#endif
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <string.h>
#include "card.h"
#include "pile.h"
#include "wx/app.h"
//+-------------------------------------------------------------+
//| Pile::Pile() |
//+-------------------------------------------------------------+
//| Description: |
//| Initialise the pile to be empty of cards. |
//+-------------------------------------------------------------+
Pile::Pile(int x, int y, int dx, int dy)
{
m_x = x;
m_y = y;
m_dx = dx;
m_dy = dy;
for (m_topCard = 0; m_topCard < NumCards; m_topCard++)
{
m_cards[m_topCard] = 0;
}
m_topCard = -1; // i.e. empty
}
//+-------------------------------------------------------------+
//| Pile::Redraw() |
//+-------------------------------------------------------------+
//| Description: |
//| Redraw the pile on the screen. If the pile is empty |
//| just draw a NULL card as a place holder for the pile. |
//| Otherwise draw the pile from the bottom up, starting |
//| at the origin of the pile, shifting each subsequent |
//| card by the pile's x and y offsets. |
//+-------------------------------------------------------------+
void Pile::Redraw(wxDC& dc )
{
wxWindow *frame = wxTheApp->GetTopWindow();
wxWindow *canvas = (wxWindow *) NULL;
if (frame)
{
wxNode *node = frame->GetChildren().First();
if (node) canvas = (wxWindow*)node->Data();
}
if (m_topCard >= 0)
{
if (m_dx == 0 && m_dy == 0)
{
if ((canvas) && (canvas->IsExposed(m_x,m_y,60,200)))
m_cards[m_topCard]->Draw(dc, m_x, m_y);
}
else
{
int x = m_x;
int y = m_y;
for (int i = 0; i <= m_topCard; i++)
{
if ((canvas) && (canvas->IsExposed(x,y,60,200)))
m_cards[i]->Draw(dc, x, y);
x += m_dx;
y += m_dy;
}
}
}
else
{
if ((canvas) && (canvas->IsExposed(m_x,m_y,60,200)))
Card::DrawNullCard(dc, m_x, m_y);
}
}
//+-------------------------------------------------------------+
//| Pile::GetTopCard() |
//+-------------------------------------------------------------+
//| Description: |
//| Return a pointer to the top card in the pile or NULL |
//| if the pile is empty. |
//| NB: Gets a copy of the card without removing it from the |
//| pile. |
//+-------------------------------------------------------------+
Card* Pile::GetTopCard()
{
Card* card = 0;
if (m_topCard >= 0)
{
card = m_cards[m_topCard];
}
return card;
}
//+-------------------------------------------------------------+
//| Pile::RemoveTopCard() |
//+-------------------------------------------------------------+
//| Description: |
//| If the pile is not empty, remove the top card from the |
//| pile and return the pointer to the removed card. |
//| If the pile is empty return a NULL pointer. |
//+-------------------------------------------------------------+
Card* Pile::RemoveTopCard()
{
Card* card = 0;
if (m_topCard >= 0)
{
card = m_cards[m_topCard--];
}
return card;
}
//+-------------------------------------------------------------+
//| Pile::RemoveTopCard() |
//+-------------------------------------------------------------+
//| Description: |
//| As RemoveTopCard() but also redraw the top of the pile |
//| after the card has been removed. |
//| NB: the offset allows for the redrawn area to be in a |
//| bitmap ready for 'dragging' cards acrosss the screen. |
//+-------------------------------------------------------------+
Card* Pile::RemoveTopCard(wxDC& dc, int xOffset, int yOffset)
{
int topX, topY, x, y;
GetTopCardPos(topX, topY);
Card* card = RemoveTopCard();
if (card)
{
card->Erase(dc, topX - xOffset, topY - yOffset);
GetTopCardPos(x, y);
if (m_topCard < 0)
{
Card::DrawNullCard(dc, x - xOffset, y - yOffset);
}
else
{
m_cards[m_topCard]->Draw(dc, x - xOffset, y - yOffset);
}
}
return card;
}
void Pile::GetTopCardPos(int& x, int& y)
{
if (m_topCard < 0)
{
x = m_x;
y = m_y;
}
else
{
x = m_x + m_dx * m_topCard;
y = m_y + m_dy * m_topCard;
}
}
void Pile::AddCard(Card* card)
{
if (m_topCard < -1) m_topCard = -1;
m_cards[++m_topCard] = card;
}
void Pile::AddCard(wxDC& dc, Card* card)
{
AddCard(card);
int x, y;
GetTopCardPos(x, y);
card->Draw(dc, x, y);
}
// Can the card leave this pile.
// If it is a member of the pile then the answer is yes.
// Derived classes may override this behaviour to incorporate
// the rules of the game
bool Pile::CanCardLeave(Card* card)
{
for (int i = 0; i <= m_topCard; i++)
{
if (card == m_cards[i]) return TRUE;
}
return FALSE;
}
// Calculate how far x, y is from top card in the pile
// Returns the square of the distance
int Pile::CalcDistance(int x, int y)
{
int cx, cy;
GetTopCardPos(cx, cy);
return ((cx - x) * (cx - x) + (cy - y) * (cy - y));
}
// Return the card at x, y. Check the top card first, then
// work down the pile. If a card is found then return a pointer
// to the card, otherwise return NULL
Card* Pile::GetCard(int x, int y)
{
int cardX;
int cardY;
GetTopCardPos(cardX, cardY);
for (int i = m_topCard; i >= 0; i--)
{
if (x >= cardX && x <= cardX + CardWidth &&
y >= cardY && y <= cardY + CardHeight)
{
return m_cards[i];
}
cardX -= m_dx;
cardY -= m_dy;
}
return 0;
}
// Return the position of the given card. If it is not a member of this pile
// return the origin of the pile.
void Pile::GetCardPos(Card* card, int& x, int& y)
{
x = m_x;
y = m_y;
for (int i = 0; i <= m_topCard; i++)
{
if (card == m_cards[i])
{
return;
}
x += m_dx;
y += m_dy;
}
// card not found in pile, return origin of pile
x = m_x;
y = m_y;
}
bool Pile::Overlap(int x, int y)
{
int cardX;
int cardY;
GetTopCardPos(cardX, cardY);
if (x >= cardX - CardWidth && x <= cardX + CardWidth &&
y >= cardY - CardHeight && y <= cardY + CardHeight)
{
return TRUE;
}
return FALSE;
}
Pile::~Pile()
{
// nothing special at the moment
}

80
demos/forty/pile.h Normal file
View File

@@ -0,0 +1,80 @@
/////////////////////////////////////////////////////////////////////////////
// Name: pile.h
// Purpose: Forty Thieves patience game
// Author: Chris Breeze
// Modified by:
// Created: 21/07/97
// RCS-ID: $Id$
// Copyright: (c) 1993-1998 Chris Breeze
// Licence: wxWindows licence
//---------------------------------------------------------------------------
// Last modified: 22nd July 1998 - ported to wxWindows 2.0
/////////////////////////////////////////////////////////////////////////////
//+-------------------------------------------------------------+
//| Description: |
//| The base class for holding piles of playing cards. |
//| This is the basic building block for card games. A pile |
//| has a position on the screen and an offset for each |
//| card placed on it e.g. a pack has no offset, but the |
//| discard pile may be fanned out across the screen. |
//| |
//| The pile knows how to draw itself, though this may be |
//| overridden if the default layout needs to be changed. |
//| One or more cards can be removed from the top of a pile, |
//| and single cards can be added to the top of a pile. |
//| Functions are provided which redraw the screen when |
//| cards are added or removed. |
//| |
//| Cards know which way up they are and how to draw |
//| themselves. Piles are lists of cards. Piles know which |
//| cards they contain and where they are to be drawn. |
//+-------------------------------------------------------------+
#ifndef _PILE_H_
#define _PILE_H_
#include "card.h"
const int NumCards = 2 * PackSize;
//----------------------------------------------------------------//
// A class defining a pile of cards with a position on the screen //
//----------------------------------------------------------------//
class Pile {
public:
Pile(int x, int y, int dx = 0, int dy = 0);
virtual ~Pile();
// General functions
virtual void ResetPile() { m_topCard = -1; }
virtual void Redraw(wxDC& pDC);
// Card query functions
virtual Card* GetCard(int x, int y); // Get pointer to card at x, y
Card* GetTopCard(); // Get pointer to top card
virtual void GetCardPos(Card* card, int& x, int& y);
// Get position of a card
virtual void GetTopCardPos(int& x, int& y);
// Get position of the top card
int GetNumCards() { return m_topCard + 1; } // Number of cards in pile
bool Overlap(int x, int y); // does card at x,y overlap the pile?
int CalcDistance(int x, int y); // calculates the square of the distance
// of a card at (x,y) from the top of the pile
// Functions removing one or more cards from the top of a pile
virtual bool CanCardLeave(Card* card);
Card* RemoveTopCard();
virtual Card* RemoveTopCard(wxDC& pDC, int xOffset = 0, int yOffset = 0);
// Functions to add a card to the top of a pile
virtual bool AcceptCard(Card*) { return FALSE; }
virtual void AddCard(Card* card); // Add card to top of pile
virtual void AddCard(wxDC& pDC, Card* card); // Add card + redraw it
protected:
int m_x, m_y; // Position of the pile on the screen
int m_dx, m_dy; // Offset when drawing the pile
Card* m_cards[NumCards]; // Array of cards in this pile
int m_topCard; // Array index of the top card
};
#endif // _PILE_H_

188
demos/forty/playerdg.cpp Normal file
View File

@@ -0,0 +1,188 @@
/////////////////////////////////////////////////////////////////////////////
// Name: playerdg.cpp
// Purpose: Forty Thieves patience game
// Author: Chris Breeze
// Modified by:
// Created: 21/07/97
// RCS-ID: $Id$
// Copyright: (c) 1993-1998 Chris Breeze
// Licence: wxWindows licence
//---------------------------------------------------------------------------
// Last modified: 22nd July 1998 - ported to wxWindows 2.0
/////////////////////////////////////////////////////////////////////////////
#ifdef __GNUG__
#pragma implementation
#pragma interface
#endif
// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
#include "scorefil.h"
#include "playerdg.h"
const int ID_LISTBOX = 101;
BEGIN_EVENT_TABLE(PlayerSelectionDialog, wxDialog)
EVT_SIZE(PlayerSelectionDialog::OnSize)
EVT_BUTTON(wxID_OK, PlayerSelectionDialog::ButtonCallback)
EVT_BUTTON(wxID_CANCEL, PlayerSelectionDialog::ButtonCallback)
EVT_LISTBOX(ID_LISTBOX, PlayerSelectionDialog::SelectCallback)
EVT_CLOSE(PlayerSelectionDialog::OnCloseWindow)
END_EVENT_TABLE()
PlayerSelectionDialog::PlayerSelectionDialog(
wxWindow* parent,
ScoreFile* file
) :
wxDialog(parent, -1, "Player Selection",
wxDefaultPosition, wxSize(320, 200),
wxDIALOG_MODAL | wxDEFAULT_DIALOG_STYLE),
m_scoreFile(file)
{
// enable constraints
SetAutoLayout (TRUE);
wxStaticText* msg = new wxStaticText(this, -1, "Please select a name from the list");
wxListBox* list = new wxListBox(
this, ID_LISTBOX,
wxDefaultPosition, wxDefaultSize,
0, 0,
wxLB_SINGLE
);
wxArrayString players;
m_scoreFile->GetPlayerList(players);
for (unsigned int i = 0; i < players.Count(); i++)
{
list->Append(players[i]);
}
m_textField = new wxTextCtrl(this, -1, "", wxDefaultPosition, wxDefaultSize, 0);
m_OK = new wxButton(this, wxID_OK, "OK");
m_cancel = new wxButton(this, wxID_CANCEL, "Cancel");
wxLayoutConstraints* layout;
// Constrain the msg at the top of the window
layout = new wxLayoutConstraints;
layout->left.SameAs (this, wxLeft, 10);
layout->top.SameAs (this, wxTop, 10);
layout->height.AsIs();
layout->width.AsIs();
msg->SetConstraints(layout);
// Constrain the OK button
layout = new wxLayoutConstraints;
layout->left.SameAs (this, wxLeft, 10);
layout->bottom.SameAs (this, wxBottom, 10);
layout->height.AsIs();
layout->width.AsIs();
m_OK->SetConstraints(layout);
// Constrain the OK button
layout = new wxLayoutConstraints;
layout->left.RightOf (m_OK, 10);
layout->bottom.SameAs (this, wxBottom, 10);
layout->height.AsIs();
layout->width.AsIs();
m_cancel->SetConstraints(layout);
// Constrain the Name text entry field
layout = new wxLayoutConstraints;
layout->left.SameAs (this, wxLeft, 10);
layout->right.SameAs (this, wxRight, 10);
layout->bottom.SameAs (m_OK, wxTop, 10);
layout->height.AsIs();
m_textField->SetConstraints(layout);
// Constrain the list of players
layout = new wxLayoutConstraints;
layout->left.SameAs (this, wxLeft, 10);
layout->right.SameAs (this, wxRight, 10);
layout->top.Below (msg, 10);
layout->bottom.SameAs (m_textField, wxTop, 10);
list->SetConstraints(layout);
wxString prevPlayer = m_scoreFile->GetPreviousPlayer();
if (prevPlayer.Length() > 0)
{
list->SetStringSelection(prevPlayer);
m_textField->SetValue(prevPlayer);
}
Layout();
}
PlayerSelectionDialog::~PlayerSelectionDialog()
{
}
void PlayerSelectionDialog::OnSize(wxSizeEvent& WXUNUSED(event))
{
Layout();
}
const wxString& PlayerSelectionDialog::GetPlayersName()
{
/*
m_player = "";
Show(TRUE);
*/
return m_player;
}
void PlayerSelectionDialog::OnCloseWindow(wxCloseEvent& event)
{
m_player = "";
EndModal(wxID_CANCEL);
}
void PlayerSelectionDialog::SelectCallback(wxCommandEvent& event)
{
if (event.GetEventType() == wxEVT_COMMAND_LISTBOX_SELECTED)
{
// if (event.IsSelection())
m_textField->SetValue(event.GetString());
}
}
void PlayerSelectionDialog::ButtonCallback(wxCommandEvent& event)
{
if (event.GetId() == wxID_OK)
{
wxString name = m_textField->GetValue();
if (!name.IsNull() && name.Length() > 0)
{
if (name.Contains('@'))
{
wxMessageBox("Names should not contain the '@' character", "Forty Thieves");
}
else
{
m_player = name;
EndModal(wxID_OK);
}
}
else
{
wxMessageBox("Please enter your name", "Forty Thieves");
}
}
else
{
m_player = "";
EndModal(wxID_CANCEL);
}
}

41
demos/forty/playerdg.h Normal file
View File

@@ -0,0 +1,41 @@
/////////////////////////////////////////////////////////////////////////////
// Name: playerdg.h
// Purpose: Forty Thieves patience game
// Author: Chris Breeze
// Modified by:
// Created: 21/07/97
// RCS-ID: $Id$
// Copyright: (c) 1993-1998 Chris Breeze
// Licence: wxWindows licence
//---------------------------------------------------------------------------
// Last modified: 22nd July 1998 - ported to wxWindows 2.0
/////////////////////////////////////////////////////////////////////////////
#ifndef _PLAYERDG_H_
#define _PLAYERDG_H_
class PlayerSelectionDialog : public wxDialog
{
public:
PlayerSelectionDialog(wxWindow* parent, ScoreFile* file);
virtual ~PlayerSelectionDialog();
const wxString& GetPlayersName();
void ButtonCallback(wxCommandEvent& event);
void SelectCallback(wxCommandEvent& event);
void OnSize(wxSizeEvent& event);
DECLARE_EVENT_TABLE()
protected:
friend void SelectCallback(wxListBox&, wxCommandEvent&);
void OnCloseWindow(wxCloseEvent& event);
private:
ScoreFile* m_scoreFile;
wxString m_player;
wxButton* m_OK;
wxButton* m_cancel;
wxTextCtrl* m_textField;
};
#endif

86
demos/forty/readme.txt Normal file
View File

@@ -0,0 +1,86 @@
Forty Thieves is a patience game played with two full packs of
cards. At the start of the game forty cards are dealt on the
eight 'bases' along the top of the window. The object of the
game is to place all the cards onto the eight 'foundations'. The
foundations are built starting with the ace and adding cards of
the same suit up to the king. Cards are dealt from the pack and
placed on the discard pile. Cards may be moved from the discard
pile or one of the bases to a base or a foundation. Only one
card can be moved at a time. Cards can only be placed on a base
if the top card of the base is of the same suit and is one
higher in pip value or the base is empty e.g. the eight of
spades can only be placed on top of the nine of spades.
When the mouse cursor is over a card which can be moved it
changes to the 'hand' cursor. The card can then be moved by
double clicking the left button.
The mouse cursor also changes to a hand when a card is dragged
by placing the cursor over the card and holding down the left
button. This feature can be enabled and disabled by selecting
the 'Helping hand' option from the Edit menu.
The 'foundations' are the eight piles of cards down the left
side of the window. When the game starts these piles are empty.
The object of the game is to place all the cards on the
foundations. An ace can be placed on any empty foundation. Other
cards can only be placed on a foundation if the top card is of
the same suit and is one lower in pip value e.g. the three of
clubs can be placed on the four of clubs.
The 'bases' are the ten piles of cards along the top of the
window. At the start of the game four cards are dealt face up on
each of the bases. A card can be added to a base if the base is
empty or if the top card is of the same suit and is one higher
in pip value e.g. the queen of hearts can be placed on the king
of hearts The top card of a base can be moved onto another base
or a foundation.
Cards can be only moved one at a time. The top card of the pack
can be dealt onto discard pile by placing the mouse cursor over
the pack and pressing the left button. The number of cards
remaining is displayed to the right of the pack.
Cards can be moved from the discard pile or the bases either by
'double-clicking' or by dragging. If the left button is
double-clicked when the mouse cursor is over a card and it can
move to another pile, it will do so. This is a quick way of
moving cards when their destination is unambiguous.
A card can be dragged by placing the mouse cursor over the card
and holding down the left button. The card will follow the mouse
cursor until the left button is released. If the card is over a
pile on which it can be placed it will be added to that pile,
otherwise it will be returned to the pile from which it was
dragged.
One point is scored for every card that is placed on a
foundation. Since there are two packs of 52 cards the maximum
score is 104. A record is kept of the number of games played,
the number of games won, the current score and the average
score. This information is displayed at bottom right of the
window and is stored on disk between games. A game is deemed to
have started if the cards have been dealt and any card has been
moved. If the game is abandoned before it is finished (i.e. by
starting a new game or closing window) it counts as a lost game.
New players can be added by selecting the 'Player' option from
the Game menu. A summary of players' scores can be displayed by
selecting the 'Scores...' option from the Game menu.
All moves are recorded and can be undone. To undo a move select
the undo menu item from the Edit menu. A quicker way of undoing
is to press the right mouse button (it doesn't matter where the
mouse cursor is). Right button undo can be enabled and disabled
by selecting the 'Right button undo' option from the Edit menu.
Pressing the right mouse button with the control key pressed
re-does a previously undone move.
An empty base or two is very useful as it gives the opportunity
to unscramble other bases. Try not to build onto kings which
obscure valuable cards as it will be difficult to get to them
later. The undo facility is very useful for going back and using
'hindsight'.
Don't be put off if you can't win every game. I reckon winning 1
in 10 is pretty good (winning 1 in 3 is excellent).

192
demos/forty/scoredg.cpp Normal file
View File

@@ -0,0 +1,192 @@
/////////////////////////////////////////////////////////////////////////////
// Name: scoredg.cpp
// Purpose: Forty Thieves patience game
// Author: Chris Breeze
// Modified by:
// Created: 21/07/97
// RCS-ID: $Id$
// Copyright: (c) 1993-1998 Chris Breeze
// Licence: wxWindows licence
//---------------------------------------------------------------------------
// Last modified: 22nd July 1998 - ported to wxWindows 2.0
/////////////////////////////////////////////////////////////////////////////
#ifdef __GNUG__
#pragma implementation
#pragma interface
#endif
// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
#if wxUSE_IOSTREAMH
#if defined(__WXMSW__) && !defined(__GNUWIN32__) && !defined(__MWERKS__)
#include <strstrea.h>
#else
#include <strstream.h>
#endif
#else
#include <strstream>
using namespace std;
#endif
#include "scorefil.h"
#include "scoredg.h"
class ScoreCanvas : public wxScrolledWindow
{
public:
ScoreCanvas(wxWindow* parent, ScoreFile* scoreFile);
virtual ~ScoreCanvas();
void OnDraw(wxDC& dc);
private:
wxFont* m_font;
wxString m_text;
};
ScoreCanvas::ScoreCanvas(wxWindow* parent, ScoreFile* scoreFile) :
wxScrolledWindow(parent)
{
#ifdef __WXGTK__
m_font = wxTheFontList->FindOrCreateFont(12, wxROMAN, wxNORMAL, wxNORMAL);
#else
m_font = wxTheFontList->FindOrCreateFont(10, wxSWISS, wxNORMAL, wxNORMAL);
#endif
wxArrayString players;
scoreFile->GetPlayerList( players);
ostrstream os;
os << "Player\tWins\tGames\tScore\n";
for (unsigned int i = 0; i < players.Count(); i++)
{
int wins, games, score;
scoreFile->ReadPlayersScore(players[i], wins, games, score);
int average = 0;
if (games > 0)
{
average = (2 * score + games) / (2 * games);
}
os << players[i] << '\t'
<< wins << '\t'
<< games << '\t'
<< average << '\n';
}
os << '\0';
char* str = os.str();
m_text = str;
delete str;
}
ScoreCanvas::~ScoreCanvas()
{
}
void ScoreCanvas::OnDraw(wxDC& dc)
{
dc.SetFont(* m_font);
const char* str = m_text;
unsigned int tab = 0;
unsigned int tabstops[] = { 5, 100, 150, 200 };
// get the line spacing for the current font
int lineSpacing;
{
long w, h;
dc.GetTextExtent("Testing", &w, &h);
lineSpacing = (int)h;
}
int y = 0;
while (*str)
{
char text[256];
char* dest = text;
while (*str && *str >= ' ') *dest++ = *str++;
*dest = '\0';
dc.DrawText(text, tabstops[tab], y);
if (*str == '\t')
{
if (tab < sizeof(tabstops) / sizeof(tabstops[0]) - 1)
{
tab++;
}
}
else if (*str == '\n')
{
tab = 0;
y += lineSpacing;
}
if (*str) str++;
}
}
BEGIN_EVENT_TABLE(ScoreDialog, wxDialog)
EVT_CLOSE(ScoreDialog::OnCloseWindow)
END_EVENT_TABLE()
ScoreDialog::ScoreDialog(
wxWindow* parent,
ScoreFile* file
) :
wxDialog(parent, -1, "Scores",
wxDefaultPosition, wxSize(310, 200),
wxDIALOG_MODAL | wxDEFAULT_DIALOG_STYLE),
m_scoreFile(file)
{
// enable constraints
SetAutoLayout (TRUE);
ScoreCanvas* list = new ScoreCanvas(this, m_scoreFile);
m_OK = new wxButton(this, wxID_OK, "OK");
wxLayoutConstraints* layout;
// Constrain the OK button
layout = new wxLayoutConstraints;
layout->left.SameAs (this, wxLeft, 10);
layout->bottom.SameAs (this, wxBottom, 10);
layout->height.AsIs();
layout->width.AsIs();
m_OK->SetConstraints(layout);
// Constrain the list of players
layout = new wxLayoutConstraints;
layout->left.SameAs (this, wxLeft, 10);
layout->right.SameAs (this, wxRight, 10);
layout->top.SameAs (this, wxTop, 10);
layout->bottom.SameAs (m_OK, wxTop, 10);
list->SetConstraints(layout);
Layout();
}
ScoreDialog::~ScoreDialog()
{
}
void ScoreDialog::Display()
{
Show(TRUE);
}
void ScoreDialog::OnCloseWindow(wxCloseEvent& event)
{
EndModal(wxID_OK);
}

34
demos/forty/scoredg.h Normal file
View File

@@ -0,0 +1,34 @@
/////////////////////////////////////////////////////////////////////////////
// Name: scoredg.h
// Purpose: Forty Thieves patience game
// Author: Chris Breeze
// Modified by:
// Created: 21/07/97
// RCS-ID: $Id$
// Copyright: (c) 1993-1998 Chris Breeze
// Licence: wxWindows licence
//---------------------------------------------------------------------------
// Last modified: 22nd July 1998 - ported to wxWindows 2.0
/////////////////////////////////////////////////////////////////////////////
#ifndef _SCOREDG_H_
#define _SCOREDG_H_
class ScoreDialog : public wxDialog
{
public:
ScoreDialog(wxWindow* parent, ScoreFile* file);
virtual ~ScoreDialog();
void Display();
protected:
void OnCloseWindow(wxCloseEvent& event);
private:
ScoreFile* m_scoreFile;
wxButton* m_OK;
DECLARE_EVENT_TABLE()
};
#endif

183
demos/forty/scorefil.cpp Normal file
View File

@@ -0,0 +1,183 @@
/////////////////////////////////////////////////////////////////////////////
// Name: scorefil.cpp
// Purpose: Forty Thieves patience game
// Author: Chris Breeze
// Modified by:
// Created: 21/07/97
// RCS-ID: $Id$
// Copyright: (c) 1993-1998 Chris Breeze
// Licence: wxWindows licence
//---------------------------------------------------------------------------
// Last modified: 14th May 1998 - ported to wxWindows 2.0
/////////////////////////////////////////////////////////////////////////////
#ifdef __GNUG__
#pragma implementation
#pragma interface
#endif
// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
#ifdef __WXGTK__
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#endif
#include "wx/textfile.h"
#include "wx/config.h"
#include "wx/fileconf.h"
#include "scorefil.h"
ScoreFile::ScoreFile(const char* appName)
{
#if 0
wxString filename;
m_configFilename << "/usr/local/share/" << appName << ".scores";
if (access(m_configFilename, F_OK) == 0)
{
if (access(m_configFilename, R_OK | W_OK) != 0)
{
// file is not r/w - use local file instead
m_configFilename = wxFileConfig::GetLocalFileName(appName);
}
}
else
{
int fd = creat(m_configFilename, 0666);
if (fd < 0)
{
// failed to create file - use local file instead
m_configFilename = wxFileConfig::GetLocalFileName(appName);
}
else
{
// ensure created file has rw-rw-rw permissions
close(fd);
}
}
#endif
m_config = new wxConfig(appName, "wxWindows", appName, "", wxCONFIG_USE_LOCAL_FILE); // only local
}
ScoreFile::~ScoreFile()
{
delete m_config;
#ifdef __WXGTK__
// ensure score file has rw-rw-rw permissions
// (wxFileConfig sets them to rw-------)
chmod(m_configFilename, 0666);
#endif
}
void ScoreFile::GetPlayerList( wxArrayString &list )
{
m_config->SetPath("/Players");
int length = m_config->GetNumberOfGroups();
if (length <= 0) return;
wxString player;
long index, i = 0;
if (m_config->GetFirstGroup(player, index))
{
list.Add( player );
i++;
while (m_config->GetNextGroup(player, index))
{
list.Add( player );
i++;
}
}
}
// Calculate an encrypted check number to prevent tampering with
// score file
long ScoreFile::CalcCheck(const char* name, int p1, int p2, int p3)
{
long check = 0;
while (*name)
{
check = (check << 1) ^ (long)*name++;
check = ((check >> 23) ^ check) & 0xFFFFFF;
}
check = (check << 1) ^ (long)p1;
check = ((check >> 23) ^ check) & 0xFFFFFF;
check = (check << 1) ^ (long)p2;
check = ((check >> 23) ^ check) & 0xFFFFFF;
check = (check << 1) ^ (long)p3;
check = ((check >> 23) ^ check) & 0xFFFFFF;
return check;
}
wxString ScoreFile::GetPreviousPlayer() const
{
wxString result;
m_config->SetPath("/General");
m_config->Read("LastPlayer", &result);
return result;
}
void ScoreFile::ReadPlayersScore(
const char* player,
int& wins,
int& games,
int& score)
{
long check;
long myWins, myGames, myScore;
games = wins = score = 0;
m_config->SetPath("/Players");
m_config->SetPath(player);
if (m_config->Read("Score", &myScore, 0L) &&
m_config->Read("Games", &myGames, 0L) &&
m_config->Read("Wins", &myWins, 0L) &&
m_config->Read("Check", &check, 0L))
{
if (check != CalcCheck(player, myGames, myWins, myScore))
{
wxMessageBox("Score file corrupted", "Warning",
wxOK | wxICON_EXCLAMATION);
}
else
{
games = myGames;
wins = myWins;
score = myScore;
}
}
WritePlayersScore(player, wins, games, score);
}
void ScoreFile::WritePlayersScore(const char* player, int wins, int games, int score)
{
if (player)
{
m_config->SetPath("/General");
m_config->Write("LastPlayer", wxString(player)); // Without wxString tmp, thinks it's bool in VC++
m_config->SetPath("/Players");
m_config->SetPath(player);
m_config->Write("Score", (long)score);
m_config->Write("Games", (long)games);
m_config->Write("Wins", (long)wins);
m_config->Write("Check", CalcCheck(player, games, wins, score));
}
}

37
demos/forty/scorefil.h Normal file
View File

@@ -0,0 +1,37 @@
/////////////////////////////////////////////////////////////////////////////
// Name: scorefil.h
// Purpose: Forty Thieves patience game
// Author: Chris Breeze
// Modified by:
// Created: 21/07/97
// RCS-ID: $Id$
// Copyright: (c) 1993-1998 Chris Breeze
// Licence: wxWindows licence
//---------------------------------------------------------------------------
// Last modified: 22nd July 1998 - ported to wxWindows 2.0
/////////////////////////////////////////////////////////////////////////////
#ifndef _SCOREFILE_H_
#define _SCOREFILE_H_
#include <wx/config.h>
class wxConfig;
class ScoreFile {
public:
ScoreFile(const char* appName);
virtual ~ScoreFile();
void GetPlayerList( wxArrayString &list );
wxString GetPreviousPlayer() const;
void ReadPlayersScore(const char* player, int& wins, int& games, int &score);
void WritePlayersScore(const char* player, int wins, int games, int score);
private:
long CalcCheck(const char* name, int p1, int p2, int p3);
wxString m_configFilename;
wxConfig* m_config;
};
#endif

BIN
demos/forty/symbols.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 662 B

37
demos/forty/symbols.xbm Normal file
View File

@@ -0,0 +1,37 @@
#define Symbols_width 79
#define Symbols_height 50
static char Symbols_bits[] = {
0x08,0x84,0x0d,0x01,0x00,0x00,0x00,0x00,0x00,0x80,0x1c,0xce,0x9f,0x03,0x00,
0x00,0x00,0x00,0x00,0x80,0x2a,0xdf,0xdf,0x07,0x00,0x00,0x00,0x00,0x00,0x80,
0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x80,0x2a,0x9f,0xcf,0x07,0x00,
0x00,0x00,0x00,0x00,0x80,0x08,0x0e,0x07,0x01,0x00,0x00,0x00,0x00,0x00,0x80,
0x1c,0x04,0x82,0x03,0x00,0x00,0x00,0x00,0x00,0x80,0x1c,0x04,0x82,0x03,0x00,
0x00,0x00,0x00,0x00,0x80,0x08,0x0e,0x07,0x01,0x00,0x00,0x00,0x00,0x00,0x80,
0x2a,0x9f,0xcf,0x07,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0x0f,0x00,
0x00,0x00,0x00,0x00,0x80,0x2a,0xdf,0xdf,0x07,0x00,0x00,0x00,0x00,0x00,0x80,
0x1c,0xce,0x9f,0x03,0x00,0x00,0x00,0x00,0x00,0x80,0x08,0x84,0x0d,0x01,0x00,
0x00,0x00,0x00,0x00,0x80,0x70,0x00,0x01,0x63,0x40,0x00,0x00,0x00,0x00,0x80,
0xf8,0x80,0x83,0xf7,0xe0,0x00,0x00,0x00,0x00,0x80,0xf8,0x80,0xc3,0xff,0xf1,
0x01,0x00,0x00,0x00,0x80,0x70,0xc0,0xc7,0xff,0xf9,0x03,0x00,0x00,0x00,0x80,
0x26,0xe3,0xcf,0xff,0xfd,0x07,0x00,0x00,0x00,0x80,0xaf,0xf7,0xdf,0xff,0xff,
0x0f,0x00,0x00,0x00,0x80,0xff,0xe7,0x8f,0xff,0xfe,0x0f,0x00,0x00,0x00,0x80,
0xaf,0xc7,0x07,0x7f,0x5e,0x0f,0x00,0x00,0x00,0x80,0x26,0x83,0x03,0x3e,0x4c,
0x06,0x00,0x00,0x00,0x80,0x70,0x80,0x03,0x1c,0xe0,0x00,0x00,0x00,0x00,0x80,
0xfc,0x01,0x01,0x08,0xf8,0x03,0x00,0x00,0x00,0x80,0xfc,0x01,0x01,0x08,0xf8,
0x03,0x00,0x00,0x00,0x80,0x70,0x80,0x03,0x1c,0xe0,0x00,0x00,0x00,0x00,0x80,
0x26,0x83,0x03,0x3e,0x4c,0x06,0x00,0x00,0x00,0x80,0xaf,0xc7,0x07,0x7f,0x5e,
0x0f,0x00,0x00,0x00,0x80,0xff,0xe7,0x8f,0xff,0xfe,0x0f,0x00,0x00,0x00,0x80,
0xaf,0xf7,0xdf,0xff,0xff,0x0f,0x00,0x00,0x00,0x80,0x26,0xe3,0xcf,0xff,0xfd,
0x07,0x00,0x00,0x00,0x80,0x70,0xc0,0xc7,0xff,0xf9,0x03,0x00,0x00,0x00,0x80,
0xf8,0x80,0xc3,0xff,0xf1,0x01,0x00,0x00,0x00,0x80,0xf8,0x80,0x83,0xf7,0xe0,
0x00,0x00,0x00,0x00,0x80,0x70,0x00,0x01,0x63,0x40,0x00,0x00,0x00,0x00,0x80,
0x0c,0xe7,0x43,0x3e,0xe7,0x73,0x5c,0xe6,0x73,0xa2,0x92,0x08,0x61,0x82,0x00,
0x8a,0x62,0x09,0x89,0x92,0x21,0x88,0x50,0x9e,0x00,0x89,0x62,0x09,0x89,0x8a,
0x21,0xc6,0x49,0xa0,0x87,0x70,0x7c,0x09,0x89,0x86,0x3f,0x01,0xfa,0xa0,0x88,
0x88,0x60,0x09,0xa9,0x8a,0xa1,0x20,0x42,0xa2,0x88,0x88,0x50,0x29,0x49,0x92,
0xa1,0xcf,0x41,0x1c,0x87,0x70,0x48,0xc6,0xb0,0xa2,0xa1,0xcf,0x11,0x1c,0x87,
0x70,0x88,0x89,0x69,0xa2,0x21,0x28,0x12,0xa2,0x88,0x88,0x44,0x4a,0x92,0xa4,
0x3f,0x24,0xf8,0x82,0x88,0x88,0x42,0x4a,0xa8,0xa8,0x21,0xc3,0x91,0x82,0x8f,
0x70,0x5e,0x4a,0x88,0xb0,0xa1,0x80,0x50,0x3c,0x48,0x88,0x62,0x4a,0x88,0xa8,
0x92,0x48,0x30,0x20,0x28,0x88,0x62,0x4a,0x88,0xa4,0x0c,0xe7,0x13,0x3e,0xe7,
0x73,0x9c,0xe9,0x73,0xa2};

60
demos/forty/symbols.xpm Normal file
View File

@@ -0,0 +1,60 @@
/* XPM */
static char *symbols[] = {
/* width height num_colors chars_per_pixel */
" 79 50 3 1",
/* colors */
". c #ffffff",
"* c #ff0000",
"# c #000000",
/* pixels */
"...#......*....**.**....#......................................................",
"..###....***..*******..###.....................................................",
".#.#.#..*****.*******.#####....................................................",
"#######**************#######...................................................",
".#.#.#..*****..*****..#####....................................................",
"...#.....***....***.....#......................................................",
"..###.....*......*.....###.....................................................",
"..###.....*......*.....###.....................................................",
"...#.....***....***.....#......................................................",
".#.#.#..*****..*****..#####....................................................",
"#######**************#######...................................................",
".#.#.#..*****.*******.#####....................................................",
"..###....***..*******..###.....................................................",
"...#......*....**.**....#......................................................",
"....###.........*.......**...**.......#........................................",
"...#####.......***.....****.****.....###.......................................",
"...#####.......***....***********...#####......................................",
"....###.......*****...***********..#######.....................................",
".##..#..##...*******..***********.#########....................................",
"####.#.####.*********.***********###########...................................",
"###########..*******...*********.###########...................................",
"####.#.####...*****.....*******..####.#.####...................................",
".##..#..##.....***.......*****....##..#..##....................................",
"....###........***........***........###.......................................",
"..#######.......*..........*.......#######.....................................",
"..#######.......*..........*.......#######.....................................",
"....###........***........***........###.......................................",
".##..#..##.....***.......*****....##..#..##....................................",
"####.#.####...*****.....*******..####.#.####...................................",
"###########..*******...*********.###########...................................",
"####.#.####.*********.***********###########...................................",
".##..#..##...*******..***********.#########....................................",
"....###.......*****...***********..#######.....................................",
"...#####.......***....***********...#####......................................",
"...#####.......***.....****.****.....###.......................................",
"....###.........*.......**...**.......#........................................",
"..##....###..#####....#..#####..###..#####..###...###.#..##..#####..###..#...#.",
".#..#..#...#....#....##..#.....#.........#.#...#.#...##.#..#....#..#...#.#..#..",
"#....#.....#...#....#.#..####..#........#..#...#.#...##.#..#....#..#...#.#.#...",
"#....#...##...###..#..#......#.####....#....###...#####.#..#....#..#...#.##....",
"######..#........#.#####.....#.#...#...#...#...#.....##.#..#....#..#.#.#.#.#...",
"#....#.#.....#...#....#..#...#.#...#...#...#...#....#.#.#..#.#..#..#..#..#..#..",
"#....#.#####..###.....#...###...###....#....###....#..#..##...##....##.#.#...#.",
"#....#.#####..###...#.....###...###....#....###....#...##..#...##..#.##..#...#.",
"#....#.....#.#...#..#....#...#.#...#...#...#...#..#...#..#.#..#..#..#..#..#..#.",
"######....#..#.....#####.#.....#...#...#...#...#.#....#..#.#..#....#.#.#...#.#.",
"#....#..##....###...#..#.#.....#####...#....###..####.#..#.#..#....#...#....##.",
"#....#.#.......#....#.#...####.....#..#....#...#.#...##..#.#..#....#...#...#.#.",
".#..#..#...#..#.....##.......#.....#.#.....#...#.#...##..#.#..#....#...#..#..#.",
"..##....###..#####..#....#####..###..#####..###...###..##..#.#####..###..#...#."
};