1///////////////////////////////////////////////////////////////////////////// 2// Name: pile.cpp 3// Purpose: Forty Thieves patience game 4// Author: Chris Breeze 5// Modified by: 6// Created: 21/07/97 7// RCS-ID: $Id: pile.cpp 35650 2005-09-23 12:56:45Z MR $ 8// Copyright: (c) 1993-1998 Chris Breeze 9// Licence: wxWindows licence 10//--------------------------------------------------------------------------- 11// Last modified: 22nd July 1998 - ported to wxWidgets 2.0 12///////////////////////////////////////////////////////////////////////////// 13//+-------------------------------------------------------------+ 14//| Description: | 15//| The base class for holding piles of playing cards. | 16//+-------------------------------------------------------------+ 17 18// For compilers that support precompilation, includes "wx/wx.h". 19#include "wx/wxprec.h" 20 21#ifdef __BORLANDC__ 22#pragma hdrstop 23#endif 24 25#ifndef WX_PRECOMP 26#include "wx/wx.h" 27#endif 28 29#include <stdlib.h> 30#include <stdio.h> 31#include <time.h> 32#include <string.h> 33#include "card.h" 34#include "pile.h" 35#include "forty.h" 36#include "canvas.h" 37 38#include "wx/app.h" 39 40//+-------------------------------------------------------------+ 41//| Pile::Pile() | 42//+-------------------------------------------------------------+ 43//| Description: | 44//| Initialise the pile to be empty of cards. | 45//+-------------------------------------------------------------+ 46Pile::Pile(int x, int y, int dx, int dy) 47{ 48 m_x = x; 49 m_y = y; 50 m_dx = dx; 51 m_dy = dy; 52 for (m_topCard = 0; m_topCard < NumCards; m_topCard++) 53 { 54 m_cards[m_topCard] = 0; 55 } 56 m_topCard = -1; // i.e. empty 57} 58 59 60//+-------------------------------------------------------------+ 61//| Pile::Redraw() | 62//+-------------------------------------------------------------+ 63//| Description: | 64//| Redraw the pile on the screen. If the pile is empty | 65//| just draw a NULL card as a place holder for the pile. | 66//| Otherwise draw the pile from the bottom up, starting | 67//| at the origin of the pile, shifting each subsequent | 68//| card by the pile's x and y offsets. | 69//+-------------------------------------------------------------+ 70void Pile::Redraw(wxDC& dc ) 71{ 72 FortyFrame *frame = (FortyFrame*) wxTheApp->GetTopWindow(); 73 wxWindow *canvas = (wxWindow *) NULL; 74 if (frame) 75 { 76 canvas = frame->GetCanvas(); 77 } 78 79 if (m_topCard >= 0) 80 { 81 if (m_dx == 0 && m_dy == 0) 82 { 83 if ((canvas) && (canvas->IsExposed(m_x,m_y,(int)(Card::GetScale()*60),(int)(Card::GetScale()*200)))) 84 m_cards[m_topCard]->Draw(dc, m_x, m_y); 85 } 86 else 87 { 88 int x = m_x; 89 int y = m_y; 90 for (int i = 0; i <= m_topCard; i++) 91 { 92 if ((canvas) && (canvas->IsExposed(x,y,(int)(Card::GetScale()*60),(int)(Card::GetScale()*200)))) 93 m_cards[i]->Draw(dc, x, y); 94 x += (int)Card::GetScale()*m_dx; 95 y += (int)Card::GetScale()*m_dy; 96 } 97 } 98 } 99 else 100 { 101 if ((canvas) && (canvas->IsExposed(m_x,m_y,(int)(Card::GetScale()*60),(int)(Card::GetScale()*200)))) 102 Card::DrawNullCard(dc, m_x, m_y); 103 } 104} 105 106 107//+-------------------------------------------------------------+ 108//| Pile::GetTopCard() | 109//+-------------------------------------------------------------+ 110//| Description: | 111//| Return a pointer to the top card in the pile or NULL | 112//| if the pile is empty. | 113//| NB: Gets a copy of the card without removing it from the | 114//| pile. | 115//+-------------------------------------------------------------+ 116Card* Pile::GetTopCard() 117{ 118 Card* card = 0; 119 120 if (m_topCard >= 0) 121 { 122 card = m_cards[m_topCard]; 123 } 124 return card; 125} 126 127 128//+-------------------------------------------------------------+ 129//| Pile::RemoveTopCard() | 130//+-------------------------------------------------------------+ 131//| Description: | 132//| If the pile is not empty, remove the top card from the | 133//| pile and return the pointer to the removed card. | 134//| If the pile is empty return a NULL pointer. | 135//+-------------------------------------------------------------+ 136Card* Pile::RemoveTopCard() 137{ 138 Card* card = 0; 139 140 if (m_topCard >= 0) 141 { 142 card = m_cards[m_topCard--]; 143 } 144 return card; 145} 146 147 148//+-------------------------------------------------------------+ 149//| Pile::RemoveTopCard() | 150//+-------------------------------------------------------------+ 151//| Description: | 152//| As RemoveTopCard() but also redraw the top of the pile | 153//| after the card has been removed. | 154//| NB: the offset allows for the redrawn area to be in a | 155//| bitmap ready for 'dragging' cards acrosss the screen. | 156//+-------------------------------------------------------------+ 157Card* Pile::RemoveTopCard(wxDC& dc, int xOffset, int yOffset) 158{ 159 int topX, topY, x, y; 160 161 GetTopCardPos(topX, topY); 162 Card* card = RemoveTopCard(); 163 164 if (card) 165 { 166 card->Erase(dc, topX - xOffset, topY - yOffset); 167 GetTopCardPos(x, y); 168 if (m_topCard < 0) 169 { 170 Card::DrawNullCard(dc, x - xOffset, y - yOffset); 171 } 172 else 173 { 174 m_cards[m_topCard]->Draw(dc, x - xOffset, y - yOffset); 175 } 176 } 177 178 return card; 179} 180 181 182void Pile::GetTopCardPos(int& x, int& y) 183{ 184 if (m_topCard < 0) 185 { 186 x = m_x; 187 y = m_y; 188 } 189 else 190 { 191 x = m_x + (int)Card::GetScale()*m_dx * m_topCard; 192 y = m_y + (int)Card::GetScale()*m_dy * m_topCard; 193 } 194} 195 196void Pile::AddCard(Card* card) 197{ 198 if (m_topCard < -1) m_topCard = -1; 199 200 m_cards[++m_topCard] = card; 201} 202 203void Pile::AddCard(wxDC& dc, Card* card) 204{ 205 AddCard(card); 206 int x, y; 207 GetTopCardPos(x, y); 208 card->Draw(dc, x, y); 209} 210 211// Can the card leave this pile. 212// If it is a member of the pile then the answer is yes. 213// Derived classes may override this behaviour to incorporate 214// the rules of the game 215bool Pile::CanCardLeave(Card* card) 216{ 217 for (int i = 0; i <= m_topCard; i++) 218 { 219 if (card == m_cards[i]) return true; 220 } 221 return false; 222} 223 224// Calculate how far x, y is from top card in the pile 225// Returns the square of the distance 226int Pile::CalcDistance(int x, int y) 227{ 228 int cx, cy; 229 GetTopCardPos(cx, cy); 230 return ((cx - x) * (cx - x) + (cy - y) * (cy - y)); 231} 232 233 234// Return the card at x, y. Check the top card first, then 235// work down the pile. If a card is found then return a pointer 236// to the card, otherwise return NULL 237Card* Pile::GetCard(int x, int y) 238{ 239 int cardX; 240 int cardY; 241 GetTopCardPos(cardX, cardY); 242 243 for (int i = m_topCard; i >= 0; i--) 244 { 245 if (x >= cardX && x <= cardX + Card::GetWidth() && 246 y >= cardY && y <= cardY + Card::GetHeight()) 247 { 248 return m_cards[i]; 249 } 250 cardX -= (int)Card::GetScale()*m_dx; 251 cardY -= (int)Card::GetScale()*m_dy; 252 } 253 return 0; 254} 255 256 257// Return the position of the given card. If it is not a member of this pile 258// return the origin of the pile. 259void Pile::GetCardPos(Card* card, int& x, int& y) 260{ 261 x = m_x; 262 y = m_y; 263 264 for (int i = 0; i <= m_topCard; i++) 265 { 266 if (card == m_cards[i]) 267 { 268 return; 269 } 270 x += (int)Card::GetScale()*m_dx; 271 y += (int)Card::GetScale()*m_dy; 272 } 273 274 // card not found in pile, return origin of pile 275 x = m_x; 276 y = m_y; 277} 278 279 280bool Pile::Overlap(int x, int y) 281{ 282 int cardX; 283 int cardY; 284 GetTopCardPos(cardX, cardY); 285 286 if (x >= cardX - Card::GetWidth() && x <= cardX + Card::GetWidth() && 287 y >= cardY - Card::GetHeight() && y <= cardY + Card::GetHeight()) 288 { 289 return true; 290 } 291 return false; 292} 293