using std::string;
#define HINTBAR_MAX_HEIGHT 22
const char * GenName(string str, string ext);
//char *documentation; //see bottom this file
Kpref *kpref;
Kpref::Kpref () {
setWindowTitle("OpenPref");
initMenuBar();
mInPaintEvent = mInMouseMoveEvent = mWaitingMouseUp = false;
mDeskView = 0;
mDesktop = 0;
setMouseTracking(true);
loadOptions();
HintBar = new QStatusBar;
HintBar->setSizeGripEnabled(true);
setStatusBar(HintBar);
HintBar->setFixedHeight(HINTBAR_MAX_HEIGHT);
QDesktopWidget *desk = QApplication::desktop();
QRect dims(desk->availableGeometry(this));
int w = dims.width()-60;
//w = 528*2;
int h = dims.height()-120;
//h = 800;
int x = dims.left()+(dims.width()-w)/2;
int y = dims.top()+(dims.height()-h)/2;
move(x, y);
setMinimumWidth(CARDWIDTH*14.42);
if (CARDHEIGHT*6 > 570)
setMinimumHeight(CARDHEIGHT*6);
else
setMinimumHeight(570);
//setFixedSize(w, h);
resize(w, h);
//connect(this, SIGNAL(rejected()), qApp, SLOT(quit()));
}
void Kpref::init () {
//StatusBar1 = new QStatusBar(this);
mDeskView = new DeskView(width(), height()-HINTBAR_MAX_HEIGHT);
mDesktop = new PrefDesktop(mDeskView);
connect(mDesktop, SIGNAL(deskChanged()), this, SLOT(forceRepaint()));
connect(mDeskView, SIGNAL(deskChanged()), this, SLOT(forceRepaint()));
HintBar->showMessage(tr("Welcome to OpenPref!"));
// resize(width(),height()+HintBar->height());
}
void Kpref::resizeEvent(QResizeEvent *event) {
Q_UNUSED(event)
mDeskView->DesktopWidth=width();
mDeskView->DesktopHeight=height()-HINTBAR_MAX_HEIGHT;
mDesktop->draw();
forceRepaint();
}
Kpref::~Kpref () {
//delete StatusBar1;
//!delete formBid;
delete mDeskView;
delete mDesktop;
delete HintBar;
delete Hint;
}
void Kpref::adjustDesk () {
if (mDeskView) mDeskView->ClearScreen();
update();
}
void Kpref::initMenuBar () {
fileMenu = menuBar()->addMenu(tr("&Game"));
actNewGame = fileMenu->addAction(QIcon(QString(":/pics/newgame.png")), tr("&New game..."), this, SLOT(slotNewSingleGame()), Qt::CTRL+Qt::Key_N);
fileMenu->addSeparator();
actFileOpen = fileMenu->addAction(QIcon(QString(":/pics/fileopen.png")), tr("&Open..."), this, SLOT(slotFileOpen()), Qt::CTRL+Qt::Key_O);
actFileSave = fileMenu->addAction(QIcon(QString(":/pics/filesave.png")), tr("&Save"), this, SLOT(slotFileSave()), Qt::CTRL+Qt::Key_S);
fileMenu->addSeparator();
actOptions = fileMenu->addAction(QIcon(QString(":/pics/tool.png")), tr("&Options..."), this, SLOT(slotOptions()), Qt::CTRL+Qt::Key_P);
fileMenu->addSeparator();
//actQuit = fileMenu->addAction(QIcon(QString(":/pics/exit.png")), tr("&Quit"), qApp, SLOT(quit()), Qt::CTRL+Qt::Key_Q);
actQuit = fileMenu->addAction(QIcon(QString(":/pics/exit.png")), tr("&Quit"), this, SLOT(slotQuit()), Qt::CTRL+Qt::Key_Q);
actFileSave->setEnabled(false);
actOptions->setEnabled(true);
viewMenu = menuBar()->addMenu(tr("&Show"));
viewMenu->addAction(QIcon(QString(":/pics/paper.png")), tr("S&core..."), this, SLOT(slotShowScore()), Qt::CTRL+Qt::Key_R);
menuBar()->addSeparator();
helpMenu = menuBar()->addMenu(tr("&Help"));
helpMenu->addAction(tr("&Preferans Rules..."), this, SLOT(slotRules()), Qt::Key_F1);
helpMenu->addAction(tr("&About OpenPref"), this, SLOT(slotHelpAbout()), 0);
helpMenu->addAction(tr("About &Qt"), qApp, SLOT(aboutQt()));
//actAboutQt = helpMenu->addAction(tr("About &Qt"));
//connect(actAboutQt, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
}
///////////////////////////////////////////////////////////////////////////////
// slots
///////////////////////////////////////////////////////////////////////////////
void Kpref::slotFileOpen () {
QString fileName = QFileDialog::getOpenFileName(this, "Select saved game", "", "*.prf");
if (!fileName.isEmpty()) {
mDesktop->loadGame(fileName);
actFileSave->setEnabled(true);
mDesktop->runGame();
}
}
void Kpref::slotFileSave () {
if (mDesktop) {
QString fn = QFileDialog::getSaveFileName(this, "Select file to save the current game", "", "*.prf");
if (!fn.isEmpty()) {
fn = GenName(fn.toStdString(), "prf");
mDesktop->saveGame(fn);
}
}
}
/*
void Kpref::slotFileQuit() {
//quit();
}
*/
void Kpref::slotShowScore () {
mDesktop->closePool();
mDesktop->mShowPool = true;
mDesktop->drawPool();
mDesktop->mDeskView->mySleep(-1);
mDesktop->mShowPool = false;
mDesktop->draw();
}
void Kpref::forceRepaint () {
update();
}
void Kpref::slotNewSingleGame () {
NewGameDialog *dlg = new NewGameDialog;
// Players
dlg->leHumanName->setText(optHumanName);
dlg->leName1->setText(optPlayerName1);
dlg->cbAlphaBeta1->setChecked(optAlphaBeta1);
dlg->leName2->setText(optPlayerName2);
dlg->cbAlphaBeta2->setChecked(optAlphaBeta2);
// Conventions
dlg->sbGame->setValue(optMaxPool);
dlg->cbGreedy->setChecked(optWhistGreedy);
dlg->rbTenWhist->setChecked(opt10Whist);
dlg->cbStalin->setChecked(optStalingrad);
dlg->cbAggPass->setChecked(optAggPass);
dlg->cbWithoutThree->setChecked(optWithoutThree);
if (dlg->exec() == QDialog::Accepted) {
// Players
optHumanName = dlg->leHumanName->text();
optPlayerName1 = dlg->leName1->text();
optAlphaBeta1 = dlg->cbAlphaBeta1->isChecked();
optPlayerName2 = dlg->leName2->text();
optAlphaBeta2 = dlg->cbAlphaBeta2->isChecked();
// Conventions
optMaxPool = dlg->sbGame->value();
optWhistGreedy = dlg->cbGreedy->isChecked();
opt10Whist = dlg->rbTenWhist->isChecked();
optStalingrad = dlg->cbStalin->isChecked();
optAggPass = dlg->cbAggPass->isChecked();
optWithoutThree = dlg->cbWithoutThree->isChecked();
saveOptions();
delete dlg;
}
else
{
delete dlg;
return;
}
if (mDesktop) {
delete mDesktop;
delete mDeskView;
mDeskView = new DeskView(width(), height()-HINTBAR_MAX_HEIGHT);
mDesktop = new PrefDesktop();
mDesktop->mDeskView = mDeskView;
connect(mDesktop, SIGNAL(deskChanged()), this, SLOT(forceRepaint()));
connect(mDeskView, SIGNAL(deskChanged()), this, SLOT(forceRepaint()));
}
optPassCount = 0;
actFileOpen->setEnabled(false);
actFileSave->setEnabled(true);
mDesktop->runGame();
actFileOpen->setEnabled(true);
actFileSave->setEnabled(false);
}
void Kpref::mouseMoveEvent (QMouseEvent *event) {
if (mInMouseMoveEvent) return;
mInMouseMoveEvent = true;
Player *plr = mDesktop->currentPlayer();
if (plr) plr->hilightCard(event->x(), event->y());
mInMouseMoveEvent = false;
}
void Kpref::mousePressEvent (QMouseEvent *event) {
mWaitingMouseUp = true;
if (event->button() == Qt::LeftButton) {
mDeskView->Event = 1;
Player *plr = mDesktop->currentPlayer();
if (plr) {
plr->mClickX = event->x();
plr->mClickY = event->y();
}
}
mWaitingMouseUp = false;
}
void Kpref::keyPressEvent (QKeyEvent *event) {
if (mDeskView) {
switch (event->key()) {
case Qt::Key_Escape:
case Qt::Key_Enter:
case Qt::Key_Return:
case Qt::Key_Space:
mDeskView->Event = 2;
break;
default: ;
}
}
}
void Kpref::paintEvent (QPaintEvent *event) {
Q_UNUSED(event)
if (mInPaintEvent) return;
mInPaintEvent = true;
if (mDeskView) {
mDeskView->DesktopHeight = height()-HINTBAR_MAX_HEIGHT;
mDeskView->DesktopWidth = width();
}
if (mDeskView && mDeskView->mDeskBmp) {
QPainter p;
p.begin(this);
//p.drawPixmap(0, 0, *(mDeskView->mDeskBmp));
p.drawImage(0, 0, *(mDeskView->mDeskBmp));
p.end();
}
mInPaintEvent = false;
}
void Kpref::closeEvent(QCloseEvent *event) {
int ret;
if (!mDesktop->mGameRunning)
exit(0);
ret = QMessageBox::question(this, tr("OpenPref"),
tr("Do you really want to quit the game?"),
QMessageBox::Yes | QMessageBox::Default,
QMessageBox::No | QMessageBox::Escape);
if (ret == QMessageBox::Yes)
exit(0);
else
event->ignore();
}
void Kpref::slotHelpAbout () {
QMessageBox::about(this, tr("About"),
tr("♠ ♦ OpenPref 0.1.3 ♣ ♥
"
"More information on
http://sourceforge.net/projects/openpref
"
"Get latest sources on
http://gitorious.org/openprefqt4
\n"
"
Copyright ©2000-2009, OpenPref Developers:
I.Azarniy, A.V.Fedotov, Ketmar Dark, K.Tokarev
"
"
"
"OpenPref is free software; you can redistribute it and/or modify
"
"it under the terms of the GNU General Public License (see file
"
"COPYING or http://www.gnu.org/licenses)")
);
}
void Kpref::saveOptions () {
QSettings st;
st.setValue("maxpool", optMaxPool);
st.setValue("stalin", optStalingrad);
st.setValue("whist10", opt10Whist);
st.setValue("whistgreedy", optWhistGreedy);
st.setValue("animdeal", optDealAnim);
st.setValue("animtake", optTakeAnim);
st.setValue("humanname", optHumanName);
st.setValue("playername1", optPlayerName1);
st.setValue("alphabeta1", optAlphaBeta1);
st.setValue("playername2", optPlayerName2);
st.setValue("alphabeta2", optAlphaBeta2);
st.setValue("debughand", optDebugHands);
st.setValue("without3", optWithoutThree);
st.setValue("aggpass", optAggPass);
st.setValue("prefclub", optPrefClub);
}
void Kpref::loadOptions () {
QSettings st;
optMaxPool = st.value("maxpool", 10).toInt();
if (optMaxPool < 4) optMaxPool = 4; else if (optMaxPool > 1000) optMaxPool = 1000;
optStalingrad = st.value("stalin", false).toBool();
opt10Whist = st.value("whist10", false).toBool();// true => radio button checks 'check' nevertheless!
optWhistGreedy = st.value("whistgreedy", true).toBool();
optDealAnim = st.value("animdeal", true).toBool();
optTakeAnim = st.value("animtake", true).toBool();
#ifndef WIN32 // May be #ifdef POSIX?
optHumanName = st.value("humanname", getenv("USER")).toString();
#else
optHumanName = st.value("humanname", "").toString();
#endif
optPlayerName1 = st.value("playername1", tr("Player 1")).toString();
optAlphaBeta1 = (st.value("alphabeta1", false).toBool());
optPlayerName2 = st.value("playername2", tr("Player 2")).toString();
optAlphaBeta2 = (st.value("alphabeta2", false).toBool());
optWithoutThree = st.value("without3", false).toBool();
optDebugHands = st.value("debughand", false).toBool();
optAggPass = st.value("aggpass", false).toBool();
optPrefClub = st.value("prefclub", false).toBool();
}
void Kpref::slotOptions () {
bool oldPrefClub = optPrefClub;
bool oldDebugHands = optDebugHands;
OptDialog *dlg = new OptDialog;
//connect(dlg->cbPrefClub, SIGNAL(clicked()), this, SLOT(slotDeckChanged()));
dlg->cbAnimDeal->setChecked(optDealAnim);
dlg->cbAnimTake->setChecked(optTakeAnim);
dlg->cbDebugHands->setChecked(optDebugHands);
dlg->cbPrefClub->setChecked(optPrefClub);
if (dlg->exec() == QDialog::Accepted) {
optDealAnim = dlg->cbAnimDeal->isChecked();
optTakeAnim = dlg->cbAnimTake->isChecked();
optPrefClub = dlg->cbPrefClub->isChecked();
optDebugHands = dlg->cbDebugHands->isChecked();
saveOptions();
}
delete dlg;
if ((optPrefClub != oldPrefClub) || (optDebugHands != oldDebugHands))
slotDeckChanged();
}
void Kpref::slotDeckChanged () {
mDeskView->freeCards();
mDeskView->loadCards();
setMinimumWidth(CARDWIDTH*14.42);
if (CARDHEIGHT*6 > 570)
setMinimumHeight(CARDHEIGHT*6);
else
setMinimumHeight(570);
mDesktop->draw();
forceRepaint();
}
void Kpref::slotRules () {
QMessageBox::about(this, tr("Preferans Rules"), tr("Help system has not been implemented yet!\nSee http://en.wikipedia.org/wiki/Preferans"));
//HelpBrowser *dlg = new HelpBrowser;
//dlg->tbHelp->setSearchPaths(QStringList("/home/kostya/projects/Qt/doc/html"));
//dlg->tbHelp->loadResource(0, QUrl::fromLocalFile("/home/kostya/projects/Qt/doc/html/index.html"));
// delete dlg;
}
void Kpref::slotQuit () {
int ret;
if (!mDesktop->mGameRunning)
exit(0);
ret = QMessageBox::question(this, tr("OpenPref"),
tr("Do you really want to quit the game?"),
QMessageBox::Yes | QMessageBox::Default,
QMessageBox::No | QMessageBox::Escape);
if (ret == QMessageBox::Yes)
exit(0);
}
/*void Kpref::slotAbortBid () {
if ((formBid->_GamesType != showpool) && (formBid->_GamesType != zerogame))
{
slotAbort();
formBid->_GamesType = zerogame;
}
}*/
void Kpref::MoveImpossible () {
HintBar->showMessage(tr("This move is impossible"));
}
void Kpref::HintMove () {
if (mDesktop->mBiddingDone)
HintBar->showMessage(tr("Your move"));
else
HintBar->showMessage(tr("Select two cards to drop"));
}
bool Kpref::WhistType () {
int ret = QMessageBox::question(kpref, tr("Choose whist type"),
tr("Do you want to whist with opened cards?"),
QMessageBox::Yes | QMessageBox::Default,
QMessageBox::No | QMessageBox::Escape);
if (ret == QMessageBox::Yes)
return false;
else
return true;
}
const char * GenName(string str, string ext)
{
size_t dot_pos=str.rfind('.');
if (dot_pos!=string::npos)
str.replace(dot_pos+1,str.length()-dot_pos,ext);
else
{
str += ".";
str += ext;
}
return str.c_str();
}
openpref-0.1.3/src/forms/ 0000755 0001750 0001750 00000000000 11265437521 014662 5 ustar kostya kostya openpref-0.1.3/src/forms/forms.cmake 0000644 0001750 0001750 00000000515 11265177055 017016 0 ustar kostya kostya project(openpref)
SET ( HEADERS ${HEADERS}
src/forms/optform.h
src/forms/newgameform.h
src/forms/helpbrowser.h
src/forms/formbid.h
src/forms/qbidbutton.h
)
SET ( SOURCES ${SOURCES}
src/forms/optform.cpp
src/forms/newgameform.cpp
src/forms/helpbrowser.cpp
src/forms/formbid.cpp
src/forms/qbidbutton.cpp
) openpref-0.1.3/src/forms/qbidbutton.cpp 0000755 0001750 0001750 00000002503 11265177055 017547 0 ustar kostya kostya /*
* OpenPref - cross-platform Preferans game
*
* Copyright (C) 2000-2009 OpenPref Developers
* (see file AUTHORS for more details)
* Contact: annulen@users.sourceforge.net
*
* OpenPref is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (see file COPYING); if not, see
* http://www.gnu.org/licenses
*/
#include "qbidbutton.h"
QBidButton::QBidButton (eGameBid aBid, int x, int y, QWidget *parent) : QPushButton(parent), mBid(aBid) {
QString iName, oName;
iName.sprintf(":/pics/bids/s%i.png", aBid);
oName.sprintf("g%i", aBid);
setObjectName(oName);
setGeometry(x, y, 40, 27);
setMinimumSize(40, 27);
setIconSize(QSize(40, 27));
setIcon(QIcon(iName));
}
QBidButton::~QBidButton () {
}
openpref-0.1.3/src/forms/qbidbutton.h 0000755 0001750 0001750 00000002406 11265177055 017216 0 ustar kostya kostya /*
* OpenPref - cross-platform Preferans game
*
* Copyright (C) 2000-2009 OpenPref Developers
* (see file AUTHORS for more details)
* Contact: annulen@users.sourceforge.net
*
* OpenPref is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (see file COPYING); if not, see
* http://www.gnu.org/licenses
*/
#ifndef QBIDBUTTON_H
#define QBIDBUTTON_H
#include
#include
#include "prfconst.h"
class QBidButton : public QPushButton {
Q_OBJECT
public:
QBidButton (eGameBid aBid, int x, int y, QWidget *parent=0);
~QBidButton ();
inline eGameBid bid () const { return mBid; }
protected:
eGameBid mBid;
};
#endif
openpref-0.1.3/src/forms/optform.cpp 0000755 0001750 0001750 00000003241 11265177055 017062 0 ustar kostya kostya /*
* OpenPref - cross-platform Preferans game
*
* Copyright (C) 2000-2009 OpenPref Developers
* (see file AUTHORS for more details)
* Contact: annulen@users.sourceforge.net
*
* OpenPref is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (see file COPYING); if not, see
* http://www.gnu.org/licenses
*/
#include
#include
#include "optform.h"
OptDialog::OptDialog (QWidget *parent) : QDialog(parent) {
setupUi(this);
setAttribute(Qt::WA_QuitOnClose, false);
setAttribute(Qt::WA_DeleteOnClose, false);
}
void OptDialog::showEvent (QShowEvent *event) {
Q_UNUSED(event)
QWidget *parentObj = dynamic_cast(parent());
int x, y;
if (parentObj) {
QRect dims(parentObj->frameGeometry());
x = dims.left()+(dims.width()-width())/2;
y = dims.top()+(dims.height()-height())/2;
} else {
QDesktopWidget *desk = QApplication::desktop();
QRect dims(desk->availableGeometry(this));
x = dims.left()+(dims.width()-width())/2;
y = dims.top()+(dims.height()-height())/2;
}
move(x, y);
}
openpref-0.1.3/src/forms/newgameform.h 0000755 0001750 0001750 00000002337 11265177055 017355 0 ustar kostya kostya /*
* OpenPref - cross-platform Preferans game
*
* Copyright (C) 2000-2009 OpenPref Developers
* (see file AUTHORS for more details)
* Contact: annulen@users.sourceforge.net
*
* OpenPref is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (see file COPYING); if not, see
* http://www.gnu.org/licenses
*/
#ifndef NEWGAMEFORM_H
#define NEWGAMEFORM_H
#include
#include "ui_newgameform.h"
class NewGameDialog : public QDialog, public Ui_NewGameDialog {
Q_OBJECT
public:
NewGameDialog (QWidget *parent=0);
~NewGameDialog () { }
protected:
void showEvent (QShowEvent *event);
};
#endif
openpref-0.1.3/src/forms/formbid.cpp 0000755 0001750 0001750 00000014761 11265177055 017027 0 ustar kostya kostya /*
* OpenPref - cross-platform Preferans game
*
* Copyright (C) 2000-2009 OpenPref Developers
* (see file AUTHORS for more details)
* Contact: annulen@users.sourceforge.net
*
* OpenPref is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (see file COPYING); if not, see
* http://www.gnu.org/licenses
*/
#include
#include
#include
#include
#include
#include "formbid.h"
#include "prfconst.h"
FormBid *formBid;
FormBid::FormBid (QWidget *parent) : QDialog (parent) {
this->setModal(true);
setWindowTitle(tr("Bidding"));
initDialog();
}
FormBid::~FormBid () {
}
void FormBid::showEvent (QShowEvent *event) {
Q_UNUSED(event)
QWidget *parentObj = dynamic_cast(parent());
int x, y;
if (parentObj) {
QRect dims(parentObj->frameGeometry());
x = dims.left()+(dims.width()-width())/2;
y = dims.top()+(dims.height()-height())/2;
} else {
QDesktopWidget *desk = QApplication::desktop();
QRect dims(desk->availableGeometry(this));
x = dims.left()+(dims.width()-width())/2;
y = dims.top()+(dims.height()-height())/2;
}
move(x, y);
}
void FormBid::closeEvent(QCloseEvent *event) {
int ret = QMessageBox::question(this, tr("OpenPref"),
tr("Do you really want to quit the game?"),
QMessageBox::Yes | QMessageBox::Default,
QMessageBox::No | QMessageBox::Escape);
if (ret == QMessageBox::Yes)
exit(0);
else
event->ignore();
}
void FormBid::slotPushButtonClick86 () { _GamesType = g86; accept(); }
void FormBid::slotPushButtonClickPass () { _GamesType = gtPass; accept(); }
void FormBid::slotPushButtonClickVist () { _GamesType = whist; accept(); }
void FormBid::slotPushButtonClickHalfVist () { _GamesType = halfwhist; accept(); }
void FormBid::slotWithoutThree () { _GamesType = withoutThree; accept(); }
void FormBid::slotShowBullet () { _GamesType = (eGameBid)1; reject(); }
void FormBid::onBidClick () {
QBidButton *b = dynamic_cast(sender());
if (!b) return;
_GamesType = b->bid();
accept();
}
QList FormBid::buttonList () {
QList res;
QList wList = qFindChildren(this);
foreach (QWidget *widget, wList) {
QPushButton *b = dynamic_cast(widget);
if (b) res << b;
}
return res;
}
QList FormBid::bidButtonList () {
QList res;
QList wList = qFindChildren(this);
foreach (QWidget *widget, wList) {
QBidButton *b = dynamic_cast(widget);
if (b) res << b;
}
return res;
}
void FormBid::enableAll () {
QList wList(buttonList());
foreach (QPushButton *b, wList) b->setEnabled(true);
}
void FormBid::disableAll () {
QList wList(buttonList());
foreach (QPushButton *b, wList) b->setEnabled(false);
}
void FormBid::disableLessThan (eGameBid gameType) {
QList wList(buttonList());
foreach (QPushButton *b, wList) {
if (gameName2Type(b->objectName()) < gameType) b->setEnabled(false);
}
}
void FormBid::disableItem (eGameBid gameType) {
QList wList(buttonList());
foreach (QPushButton *b, wList) {
if (gameName2Type(b->objectName()) == gameType) b->setEnabled(false);
}
}
void FormBid::enableItem (eGameBid gameType) {
QList wList(buttonList());
foreach (QPushButton *b, wList) {
if (gameName2Type(b->objectName()) == gameType) b->setEnabled(true);
}
}
void FormBid::initDialog () {
this->resize(220, 260);
this->setMinimumSize(220, 260);
this->setMaximumSize(220, 260);
for (int face = 6; face <= 10; face++) {
int y = (face-6)*30+10;
if (face > 8)
y += 30;
for (int suit = 1; suit <= 5; suit++) {
int x = (suit-1)*40+10;
int bid = face*10+suit;
QBidButton *b = new QBidButton((eGameBid)bid, x, y, this);
if (suit == 5)
b->setToolTip(tr("no trump"));
connect(b, SIGNAL(clicked()), this, SLOT(onBidClick()));
}
}
b86 = new QPushButton(this);
b86->setGeometry(10, 100, 200, 27);
b86->setMinimumSize(0,0);
b86->setObjectName("g86");
b86->setText(tr("&Misere"));
bpass = new QPushButton(this);
bpass->setGeometry(10,190,60,30);
bpass->setMinimumSize(0,0);
bpass->setObjectName("pass");
bpass->setText(tr("&Pass"));
bpass->setIcon(QIcon(QString(":/pics/pass.png")));
bvist = new QPushButton(this);
bvist->setGeometry(150,190,60,30);
bvist->setMinimumSize(0,0);
bvist->setObjectName("whist");
bvist->setText(tr("&Whist"));
bvist->setIcon(QIcon(QString(":/pics/whist.png")));
bhalfvist = new QPushButton(this);
bhalfvist->setGeometry(70, 190, 80, 30);
bhalfvist->setMinimumSize(0,0);
bhalfvist->setObjectName("halfwhist");
bhalfvist->setText(tr("&HalfWhist"));
bhalfvist->setIcon(QIcon(QString(":/pics/halfwhist.png")));
showbullet = new QPushButton(this);
showbullet->setGeometry(116, 220, 94, 27);
showbullet->setMinimumSize(0, 0);
showbullet->setText(tr("S&core"));
showbullet->setToolTip(tr("Show game table with calculated scores"));
showbullet->setIcon(QIcon(QString(":/pics/paper.png")));
bwithoutthree = new QPushButton(this);
bwithoutthree->setGeometry(10, 220, 106, 27);
bwithoutthree->setMinimumSize(0, 0);
bwithoutthree->setText(tr("Without &Three"));
bwithoutthree->setToolTip(tr("Cancel game with penalty of three untaken tricks. No whists are written"));
bwithoutthree->setIcon(QIcon(QString(":/pics/cancel.png")));
connect(b86, SIGNAL(clicked()), this, SLOT(slotPushButtonClick86()));
connect(bpass, SIGNAL(clicked()), this, SLOT(slotPushButtonClickPass()));
connect(bvist, SIGNAL(clicked()), this, SLOT(slotPushButtonClickVist()));
connect(bhalfvist, SIGNAL(clicked()), this, SLOT(slotPushButtonClickHalfVist()));
connect(bwithoutthree, SIGNAL(clicked()), this, SLOT(slotWithoutThree()));
connect(showbullet, SIGNAL(clicked()), this, SLOT(slotShowBullet()));
}
openpref-0.1.3/src/forms/helpbrowser.h 0000644 0001750 0001750 00000002327 11265177055 017376 0 ustar kostya kostya /*
* OpenPref - cross-platform Preferans game
*
* Copyright (C) 2000-2009 OpenPref Developers
* (see file AUTHORS for more details)
* Contact: annulen@users.sourceforge.net
*
* OpenPref is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (see file COPYING); if not, see
* http://www.gnu.org/licenses
*/
#ifndef HELPBROWSER_H
#define HELPBROWSER_H
#include
#include "ui_helpbrowser.h"
class HelpBrowser : public QDialog, public Ui_HelpBrowser {
Q_OBJECT
public:
HelpBrowser (QWidget *parent=0);
~HelpBrowser () { }
protected:
void showEvent (QShowEvent *event);
};
#endif
openpref-0.1.3/src/forms/formbid.h 0000755 0001750 0001750 00000004015 11265177055 016463 0 ustar kostya kostya /*
* OpenPref - cross-platform Preferans game
*
* Copyright (C) 2000-2009 OpenPref Developers
* (see file AUTHORS for more details)
* Contact: annulen@users.sourceforge.net
*
* OpenPref is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (see file COPYING); if not, see
* http://www.gnu.org/licenses
*/
#ifndef FORMBID_H
#define FORMBID_H
#include
#include
#include
#include
#include
#include "prfconst.h"
#include "qbidbutton.h"
class FormBid : public QDialog {
Q_OBJECT
public:
FormBid (QWidget *parent=0);
~FormBid ();
void enableAll ();
void disableAll ();
void disableLessThan (eGameBid);//(eGameBid);
void disableItem (eGameBid);
void enableItem (eGameBid);
public slots:
void onBidClick (); // universal handler
void slotPushButtonClick86 ();
void slotPushButtonClickPass ();
void slotPushButtonClickVist ();
void slotPushButtonClickHalfVist ();
void slotWithoutThree ();
void slotShowBullet ();
protected:
void initDialog ();
QList buttonList ();
QList bidButtonList ();
void showEvent (QShowEvent *event);
void closeEvent(QCloseEvent *event);
public:
eGameBid _GamesType;
QPushButton *bwithoutthree;
QPushButton *showbullet;
QPushButton *bhalfvist;
protected:
QPushButton *b86;
QPushButton *bpass;
QPushButton *bvist;
};
extern FormBid *formBid;
#endif
openpref-0.1.3/src/forms/forms.pri 0000755 0001750 0001750 00000000451 11265177055 016532 0 ustar kostya kostya DEPENDPATH += $$PWD
INCLUDEPATH += $$PWD
HEADERS += \
$$PWD/optform.h \
$$PWD/newgameform.h \
$$PWD/helpbrowser.h \
$$PWD/formbid.h \
$$PWD/qbidbutton.h
SOURCES += \
$$PWD/optform.cpp \
$$PWD/newgameform.cpp \
$$PWD/helpbrowser.cpp \
$$PWD/formbid.cpp \
$$PWD/qbidbutton.cpp
openpref-0.1.3/src/forms/optform.h 0000755 0001750 0001750 00000002303 11265177055 016525 0 ustar kostya kostya /*
* OpenPref - cross-platform Preferans game
*
* Copyright (C) 2000-2009 OpenPref Developers
* (see file AUTHORS for more details)
* Contact: annulen@users.sourceforge.net
*
* OpenPref is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (see file COPYING); if not, see
* http://www.gnu.org/licenses
*/
#ifndef OPTFORM_H
#define OPTFORM_H
#include
#include "ui_optform.h"
class OptDialog : public QDialog, public Ui_OptDialog {
Q_OBJECT
public:
OptDialog (QWidget *parent=0);
~OptDialog () { }
protected:
void showEvent (QShowEvent *event);
};
#endif
openpref-0.1.3/src/forms/newgameform.cpp 0000755 0001750 0001750 00000003261 11265177055 017705 0 ustar kostya kostya /*
* OpenPref - cross-platform Preferans game
*
* Copyright (C) 2000-2009 OpenPref Developers
* (see file AUTHORS for more details)
* Contact: annulen@users.sourceforge.net
*
* OpenPref is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (see file COPYING); if not, see
* http://www.gnu.org/licenses
*/
#include
#include
#include "newgameform.h"
NewGameDialog::NewGameDialog (QWidget *parent) : QDialog(parent) {
setupUi(this);
setAttribute(Qt::WA_QuitOnClose, false);
setAttribute(Qt::WA_DeleteOnClose, false);
}
void NewGameDialog::showEvent (QShowEvent *event) {
Q_UNUSED(event)
QWidget *parentObj = dynamic_cast(parent());
int x, y;
if (parentObj) {
QRect dims(parentObj->frameGeometry());
x = dims.left()+(dims.width()-width())/2;
y = dims.top()+(dims.height()-height())/2;
} else {
QDesktopWidget *desk = QApplication::desktop();
QRect dims(desk->availableGeometry(this));
x = dims.left()+(dims.width()-width())/2;
y = dims.top()+(dims.height()-height())/2;
}
move(x, y);
}
openpref-0.1.3/src/forms/helpbrowser.cpp 0000644 0001750 0001750 00000003253 11265177055 017730 0 ustar kostya kostya /*
* OpenPref - cross-platform Preferans game
*
* Copyright (C) 2000-2009 OpenPref Developers
* (see file AUTHORS for more details)
* Contact: annulen@users.sourceforge.net
*
* OpenPref is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (see file COPYING); if not, see
* http://www.gnu.org/licenses
*/
#include
#include
#include "helpbrowser.h"
HelpBrowser::HelpBrowser (QWidget *parent) : QDialog(parent) {
setupUi(this);
setAttribute(Qt::WA_QuitOnClose, false);
setAttribute(Qt::WA_DeleteOnClose, false);
}
void HelpBrowser::showEvent (QShowEvent *event) {
Q_UNUSED(event)
QWidget *parentObj = dynamic_cast(parent());
int x, y;
if (parentObj) {
QRect dims(parentObj->frameGeometry());
x = dims.left()+(dims.width()-width())/2;
y = dims.top()+(dims.height()-height())/2;
} else {
QDesktopWidget *desk = QApplication::desktop();
QRect dims(desk->availableGeometry(this));
x = dims.left()+(dims.width()-width())/2;
y = dims.top()+(dims.height()-height())/2;
}
move(x, y);
}
openpref-0.1.3/src/logic/ 0000755 0001750 0001750 00000000000 11265437521 014631 5 ustar kostya kostya openpref-0.1.3/src/logic/aiplayer.cpp 0000755 0001750 0001750 00000162545 11265177055 017166 0 ustar kostya kostya /*
* OpenPref - cross-platform Preferans game
*
* Copyright (C) 2000-2009 OpenPref Developers
* (see file AUTHORS for more details)
* Contact: annulen@users.sourceforge.net
*
* OpenPref is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (see file COPYING); if not, see
* http://www.gnu.org/licenses
*/
#include
#include
#include
#include
#include
#include "aiplayer.h"
#include "debug.h"
AiPlayer::AiPlayer (int aMyNumber, DeskView *aDeskView) : Player(aMyNumber, aDeskView) {
internalInit();
}
void AiPlayer::clear () {
Player::clear();
for (int f = 0; f <= 4; f++) {
mSuitProb[f].tricks = 0;
mSuitProb[f].perehvatov = 0;
}
}
///////////////////////////////////////////////////////////////////////////////
// utils
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// масть с перехватами (max)
Card *AiPlayer::GetMaxCardWithOutPere () {
int index = 0, vz = 0, pere = 0;
for (int f = 1; f <= 4; f++) {
if (mSuitProb[f].tricks > vz || (mSuitProb[f].tricks == vz && mSuitProb[f].perehvatov < pere)) {
index = f;
vz = mSuitProb[f].tricks;
pere = mSuitProb[f].perehvatov;
}
}
if (index) return mCards.maxInSuit(index);
return 0;
}
///////////////////////////////////////////////////////////////////////////////
// ???
Card *AiPlayer::GetMinCardWithOutVz () {
int index = 0;
double koef = 0, koef1 = 0;
for (int f = 1; f <= 4; f++) {
koef1 = mSuitProb[f].len+8/(1+mSuitProb[f].tricks);
if ((koef1 > koef && mSuitProb[f].len != 0) || (mSuitProb[f].tricks == 0 && mSuitProb[f].len > 0)) {
index = f;
koef =koef1;
}
}
if (index && index <=4) return mCards.minInSuit(index);
return mCards.minFace();
}
///////////////////////////////////////////////////////////////////////////////
// ???
Card *AiPlayer::GetMaxCardPere () {
int index = 0, vz = 0, pere = 0;
for (int f = 1; f <= 4; f++) {
if (mSuitProb[f].tricks > vz || (mSuitProb[f].tricks == vz && mSuitProb[f].perehvatov > pere)) {
index = f;
vz = mSuitProb[f].tricks;
pere = mSuitProb[f].perehvatov;
}
}
if (index) return mCards.maxInSuit(index);
return 0;
}
tSuitProbs AiPlayer::countTricks (eSuit Mast, CardList &aMaxCardList, int a23) {
tSuitProbs suitProb;
Card *MyCard, *tmpCard;
CardList MyCardStack, EnemyCardStack;
for (int c = 7; c <= FACE_ACE; c++) {
MyCard = mCards.exists(c, Mast);
if (MyCard) MyCardStack.insert(MyCard);
MyCard = aMaxCardList.exists(c, Mast);
if (MyCard) EnemyCardStack.insert(MyCard);
}
if (a23 != 23) suitProb = calcProbsForMax(MyCardStack, EnemyCardStack);
else suitProb = calcProbsForMaxH23(MyCardStack, EnemyCardStack);
suitProb.len = mCards.cardsInSuit(Mast);
suitProb.sum = 0;
for (int j = 7; j <= FACE_ACE; j++ ) {
tmpCard = mCards.exists(j, Mast);
if (tmpCard) suitProb.sum += tmpCard->face();
}
return suitProb;
}
tSuitProbs AiPlayer::countGameTricks (eSuit Mast, int a23) {
tSuitProbs suitProb;
Card *MyCard, *tmpCard;
CardList MyCardStack, EnemyCardStack;
for (int c = 7; c <= FACE_ACE; c++) {
MyCard = mCards.exists(c, Mast);
if (MyCard) MyCardStack.insert(MyCard);
else EnemyCardStack.insert(newCard(c, Mast));
}
if (MyCardStack.count() >= 4 && MyCardStack.count() <= 5) EnemyCardStack.remove(EnemyCardStack.minFace());
if (a23 == 23) suitProb = calcProbsForMaxH23(MyCardStack, EnemyCardStack);
else suitProb = calcProbsForMax(MyCardStack, EnemyCardStack);
suitProb.len = mCards.cardsInSuit(Mast);
suitProb.sum = 0;
for (int j = 7; j <= FACE_ACE; j++) {
tmpCard = mCards.exists(j, Mast);
if (tmpCard) suitProb.sum += tmpCard->face();
}
return suitProb;
}
//-----------------------------------------------------------------------
tSuitProbs AiPlayer::countPassTricks (eSuit Mast, CardList &aMaxCardList) {
tSuitProbs suitProb;
Card *MyCard, *tmpCard;
CardList MyCardStack, EnemyCardStack;
for (int c = 7; c <= FACE_ACE; c++) {
MyCard = mCards.exists(c, Mast);
if (MyCard) MyCardStack.insert(MyCard);
MyCard = aMaxCardList.exists(c, Mast);
if (MyCard) EnemyCardStack.insert(MyCard);
}
suitProb = calcProbsForMin(MyCardStack, EnemyCardStack);
suitProb.len = mCards.cardsInSuit(Mast);
suitProb.sum = 0;
for (int j = 7; j <= FACE_ACE; j++) {
tmpCard = mCards.exists(j, Mast);
if (tmpCard) suitProb.sum += tmpCard->face();
}
return suitProb;
}
bool AiPlayer::checkForMisere () {
int cur = 0;
for (int Mast = SuitSpades; Mast <= SuitHearts; Mast++) {
if (mCards.exists(7, Mast) && (mCards.exists(9, Mast) || mCards.exists(8, Mast)) &&
(mCards.exists(FACE_JACK, Mast) || mCards.exists(10, Mast))) {
cur++;
}
}
if (cur == 4) return true;
return false;
}
//-----------------------------------------------------------------------
// Для мин результата
tSuitProbs AiPlayer::calcProbsForMin (CardList &my, CardList &enemy) {
tSuitProbs suitProb;
suitProb.tricks = 0;
suitProb.perehvatov = 0;
int nMaxLen;
Card *MyCardMin, *EnemyCardMax, *EnemyCardMin;
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//enemy->free(enemy->minFace());
nMaxLen = (my.count() > enemy.count()) ? my.count() : enemy.count() ;
//my.count()>enemy->count() ? nMaxLen = my->count() : nMaxLen = enemy->count();
for (int f = 1; f <= nMaxLen; f++) {
MyCardMin = my.minFace();
EnemyCardMax = enemy.maxFace();
if (MyCardMin) {
EnemyCardMin = enemy.lesserInSuit(MyCardMin);
if (!EnemyCardMin) EnemyCardMin = enemy.minFace();
} else {
//EnemyCardMin = enemy->minFace();
break;
}
if (!EnemyCardMax && !EnemyCardMin) break;
if (*MyCardMin > *EnemyCardMin) {
// викидываем мою его младшую
my.remove(MyCardMin);
enemy.remove(EnemyCardMin);
suitProb.tricks++;
} else {
my.remove(MyCardMin);
enemy.remove(EnemyCardMax);
}
}
return suitProb;
}
//-----------------------------------------------------------------------
// Для максимального результата на 1 руке
tSuitProbs AiPlayer::calcProbsForMax (CardList &my, CardList &enemy) {
tSuitProbs suitProb;
suitProb.tricks = 0;
suitProb.perehvatov = 0;
int nMaxLen, nIget = 1;
Card *MyCardMax = 0, *EnemyCardMax = 0, *EnemyCardMin = 0;
//my->count()>enemy->count() ? nMaxLen = my->count() : nMaxLen = enemy->count();
nMaxLen = (my.count() > enemy.count()) ? my.count() : enemy.count();
for (int f = 1; f <= nMaxLen; f++) {
MyCardMax = my.maxFace();
if (MyCardMax) {
EnemyCardMax = enemy.greaterInSuit(MyCardMax);
if (!EnemyCardMax) EnemyCardMax = enemy.minFace();
} else EnemyCardMax = enemy.maxFace();
EnemyCardMin = enemy.minFace();
if (!MyCardMax) break;
if (!EnemyCardMax && !EnemyCardMin) {
// остаток -- мои взятки
for (int j = 1; j <= my.count(); j++) suitProb.tricks++;
break;
}
if (*MyCardMax > *EnemyCardMax) {
// викидываем мою старшую, его младшую
my.remove(MyCardMax);
enemy.remove(EnemyCardMin);
suitProb.tricks++;
if (!nIget) suitProb.perehvatov++;
nIget = 1;
} else {
my.remove(MyCardMax);
enemy.remove(EnemyCardMax);
nIget = 0;
}
}
return suitProb;
}
//-----------------------------------------------------------------------
// Для максимального результата на 2 и 3 руке
tSuitProbs AiPlayer::calcProbsForMaxH23 (CardList &my, CardList &enemy) {
tSuitProbs suitProb;
suitProb.tricks = 0;
suitProb.perehvatov = 0;
int nMaxLen,nIget = 1;
Card *MyCardMax, *EnemyCardMax;
//my->count()>enemy->count() ? nMaxLen = my->count() : nMaxLen = enemy->count();
nMaxLen = (my.count() > enemy.count()) ? my.count() : enemy.count();
for (int f = 1; f <= nMaxLen; f++) {
EnemyCardMax = enemy.maxFace();
if (EnemyCardMax) {
// Пытаемся н-ти больше чеm у него
MyCardMax = my.greaterInSuit(EnemyCardMax);
if (!MyCardMax) {
// Нет у меня больше чем у него
MyCardMax = my.minFace();
if (!MyCardMax) break; // и меньше тож нет
// Меньше чем у него
my.remove(MyCardMax);
enemy.remove(EnemyCardMax);
nIget = 0;
} else {
// Есть больше чем у него
my.remove(MyCardMax);
enemy.remove(EnemyCardMax);
suitProb.tricks++;
if (!nIget) suitProb.perehvatov++;
nIget = 1;
}
} else {
// У него нет карт в данной масти! остаток -- мои взятки
if (!enemy.count()) for (int j = 1; j <= my.count(); j++) suitProb.tricks++;
//25.07.2000 for ( int j =1; j<=my->count();j++ ) suitProb.tricks++;
break;
}
}
return suitProb;
}
///////////////////////////////////////////////////////////////////////////////
// Пересчитывает таблицу дли распасов или мизера
void AiPlayer::recalcPassOutTables (CardList &aMaxCardList, int a23) {
Q_UNUSED(a23)
mSuitProb[0].tricks = 0;
mSuitProb[0].perehvatov = 0;
mSuitProb[0].sum = 0;
for (int f = 1; f <= 4; f++) {
mSuitProb[f] = countPassTricks((eSuit)f, aMaxCardList);
mSuitProb[0].tricks += mSuitProb[f].tricks;
mSuitProb[0].perehvatov += mSuitProb[f].perehvatov;
mSuitProb[0].sum += mSuitProb[f].sum;
}
}
///////////////////////////////////////////////////////////////////////////////
// Пересчитывает таблицу tSuitProbs mSuitProb[5];
void AiPlayer::recalcTables (CardList &aMaxCardList, int a23) {
int f;
mSuitProb[0].tricks = 0;
mSuitProb[0].perehvatov = 0;
mSuitProb[0].sum = 0;
for (f = 1; f <= 4; f++) {
mSuitProb[f] = countTricks((eSuit)f, aMaxCardList, a23);
mSuitProb[0].tricks += mSuitProb[f].tricks;
mSuitProb[0].perehvatov += mSuitProb[f].perehvatov;
mSuitProb[0].sum += mSuitProb[f].sum;
}
}
void AiPlayer::loadLists (Player *aLeftPlayer, Player *aRightPlayer, CardList &aMaxCardList) {
/*
int nLeftVisible = aLeftPlayer->nCardsVisible,nRightVisible = aRightPlayer->nCardsVisible;
int nCards = mCards.count();
*/
mLeft.clear();
mRight.clear();
/*
// !!!!!!!!!!!!!!!!!!!!!!!!! необходимо учитывать, что во взятках
if ( !nLeftVisible && !nRightVisible ) {
makestatfill(nCards,1); // ,1- for max list 2- for minlist
}
if ( nLeftVisible && !nRightVisible ) {
makestatfill(nCards,1); // ,1- for max list 2- for minlist
}
if ( !nLeftVisible && nRightVisible ) {
makestatfill(nCards,1); // ,1- for max list 2- for minlist
}
if ( nLeftVisible && nRightVisible ) {
*/
mLeft = aLeftPlayer->mCards;
mRight = aRightPlayer->mCards;
/*
}
*/
// Get Max List only len
/*
for (int m = 1; m <= 4; m++) {
for (int c = FACE_ACE; c >= 7; c--) {
if (mLeft.exists(c, m) || mRight.exists(c, m)) {
aMaxCardList.insert(newCard(c, m));
}
}
}
*/
for (int m = 1; m <= 4; m++) {
Card *LeftMax,*RightMax,*Max=0;
while (mLeft.cardsInSuit(m) || mRight.cardsInSuit(m)) {
LeftMax = mLeft.maxInSuit(m);
RightMax = mRight.maxInSuit(m);
if (LeftMax == 0 && RightMax == 0) {
Max = 0;
} else if (LeftMax == 0 && RightMax != 0) {
Max = RightMax;
mRight.remove(Max);
} else if (LeftMax != 0 && RightMax == 0) {
Max = LeftMax;
mLeft.remove(Max);
} else if (*LeftMax > *RightMax) {
Max = LeftMax;
mLeft.remove(LeftMax);
mRight.remove(RightMax);
} else {
Max = RightMax;
mLeft.remove(LeftMax);
mRight.remove(RightMax);
}
}
if (Max != 0) aMaxCardList.insert(newCard(Max->face(), Max->suit()));
}
mLeft.clear();
mRight.clear();
mLeft = aLeftPlayer->mCards;
mRight = aRightPlayer->mCards;
}
///////////////////////////////////////////////////////////////////////////////
// game mechanics
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// miseres, play
///////////////////////////////////////////////////////////////////////////////
// misere, my move is first
Card *AiPlayer::Miser1 (Player *aLeftPlayer, Player *aRightPlayer) {
Card *cur = 0;
if (mCards.count() == 10) {
// первый выход в 8..туз если она одна
for (int m = 1; m <= 4; m++) {
if (mCards.cardsInSuit(m) == 1) {
cur = mCards.minInSuit(m);
break;
}
}
}
if (!cur) {
for (int m = 4; m >= 1; m--) {
if (cur) break;
for (int c = FACE_ACE; c >= 7; c--) {
if (cur) break;
Card *my;
//,*leftmax,*leftmin,*rightmax,*rightmin;
my = mCards.exists(c, m);
if (my) {
int matrixindex = 0;
matrixindex += aLeftPlayer->mCards.lesserInSuit(my) ? 1:0; matrixindex <<= 1;
matrixindex += aLeftPlayer->mCards.greaterInSuit(my) ? 1:0; matrixindex <<= 1;
matrixindex += aRightPlayer->mCards.lesserInSuit(my) ? 1:0; matrixindex <<= 1;
matrixindex += aRightPlayer->mCards.greaterInSuit(my) ? 1:0;
if (matrixindex == 1 || matrixindex == 9 || matrixindex == 13 || (matrixindex >= 4 && matrixindex <= 7)) {
cur = my;
}
}
}
}
}
if (!cur) cur = mCards.minInSuit(1);
if (!cur) cur = mCards.minInSuit(2);
if (!cur) cur = mCards.minInSuit(3);
if (!cur) cur = mCards.minInSuit(4);
return cur;
}
///////////////////////////////////////////////////////////////////////////////
// misere, my move is second
Card *AiPlayer::Miser2 (Card *aRightCard, Player *aLeftPlayer, Player *aRightPlayer) {
Card *cur = 0;
if (mCards.cardsInSuit(aRightCard->suit())) {
for (int c = FACE_ACE; c >= 7; c--) {
if (cur) break;
Card *my;
//,*leftmax,*leftmin,*rightmax,*rightmin;
my = mCards.exists(c, aRightCard->suit());
if (my) {
int matrixindex = 0;
matrixindex += aLeftPlayer->mCards.lesserInSuit(my) ? 1:0; matrixindex <<= 1;
matrixindex += aLeftPlayer->mCards.greaterInSuit(my) ? 1:0; matrixindex <<= 1;
matrixindex += (*aRightCard < *my) ? 1:0; matrixindex <<= 1;
matrixindex += (*aRightCard > *my) ? 1:0;
if (matrixindex == 1 || matrixindex == 9 || matrixindex==13 || (matrixindex >= 4 && matrixindex <= 7)) {
cur = my;
}
}
}
if (!cur) cur = mCards.maxInSuit(aRightCard->suit());
} else {
CardList aMaxCardList;
loadLists(aRightPlayer, aLeftPlayer, aMaxCardList);
cur = GetMaxCardWithOutPere();
if (!cur) cur = GetMaxCardPere(); // масть с перехватами (max)
if (!cur) cur = GetMinCardWithOutVz(); // лабуду
if (!cur) cur = mCards.maxFace();
}
return cur;
}
///////////////////////////////////////////////////////////////////////////////
// misere, my move is third
Card *AiPlayer::Miser3 (Card *aLeftCard, Card *aRightCard, Player *aLeftPlayer, Player *aRightPlayer) {
// copy from MyPass3
Card *cur = 0;
eGameBid tmpGamesType = mMyGame;
CardList aMaxCardList;
//int mast = mMyGame-(mMyGame/10)*10;
// набираем списки
loadLists(aLeftPlayer, aRightPlayer, aMaxCardList);
recalcPassOutTables(aMaxCardList, 23);
if (mCards.cardsInSuit(aLeftCard->suit())) {
// у меня есть масть в которую зашел левый; постараемся пропустить
if (aLeftCard->suit() == aRightCard->suit()) {
cur = (*aRightCard > *aLeftCard) ?
mCards.lesserInSuit(aRightCard) :
mCards.lesserInSuit(aLeftCard);
} else cur = mCards.lesserInSuit(aLeftCard);
if (!cur) cur = mCards.maxInSuit(aLeftCard->suit());
} else {
// у меня нет масти в которую зашел левый
cur = GetMaxCardWithOutPere();
if (!cur) cur = GetMaxCardPere(); // масть с перехватами (max)
if (!cur) cur = GetMinCardWithOutVz(); // лабуду
if (!cur) cur = mCards.minFace();
}
mMyGame = tmpGamesType;
return cur;
}
///////////////////////////////////////////////////////////////////////////////
// miseres, catch
///////////////////////////////////////////////////////////////////////////////
// misere catch, my move is first
Card *AiPlayer::MiserCatch1 (Player *aLeftPlayer, Player *aRightPlayer) {
Card *cur = 0;
CardList aMaxCardList;
CardList *Naparnik;
eHand Side;
if (aRightPlayer->myGame() == g86) {
loadLists(aRightPlayer, aRightPlayer, aMaxCardList);
Naparnik = &(aLeftPlayer->mCards);
Side = RightHand;
} else {
loadLists(aLeftPlayer, aLeftPlayer, aMaxCardList);
Naparnik = &(aRightPlayer->mCards);
Side = LeftHand;
}
recalcPassOutTables(aMaxCardList, 1);
// Randomization
int suit[4];
int s;
for (int i=0; i<4; i++) {
s=0;
while (s==0) {
s = qrand()%4+1;
for (int j=0; jminInSuit(m);
Card *MyMin = mCards.minInSuit(m);
if (cur) goto badlabel;
if (EnemyMin) {
//есть такая
if (MyMin) {
// и у меня есть такая
if (NaparnikMin) {
// и у напарника есть такая
if (*NaparnikMin < *EnemyMin && *MyMin < *EnemyMin) {
cur = MyMin;// Всунули
goto badlabel;
}
if (*NaparnikMin > *EnemyMin && *MyMin < *EnemyMin) {
// надо н-ти такую масть по которой он может пронести а
// но должен вернутся ко мне
for (int k = 1; k <= 4; k++) {
if (k == m || aMaxCardList.cardsInSuit(k) == 0) continue;
Card *EnemyMax = aMaxCardList.maxInSuit(k);
Card *NaparnikMax = Naparnik->maxInSuit(k);
Card *MyMax = mCards.maxInSuit(k);
if (MyMax && NaparnikMax && EnemyMax) {
if (Naparnik->cardsInSuit(k) < mCards.cardsInSuit(k) &&
Naparnik->cardsInSuit(k) < aMaxCardList.cardsInSuit(k)) {
cur = mCards.lesserInSuit(EnemyMax);
//MyMax; // на этой он должен пронести NaparnikMax
if (aRightPlayer->myGame() == g86) aRightPlayer->mCardCarryThru = NaparnikMax;
else aLeftPlayer->mCardCarryThru = NaparnikMax;
goto badlabel;
}
}
}
}
} else { //у напорника нет масти
if (*MyMin < *EnemyMin) {
cur = MyMin;// Всунули
goto badlabel;
}
}
}
}
}
if ((Side == LeftHand) && (!cur))
// if we didn't choose anything wise, move lesser card
cur = mCards.minFace();
else {
//2 отгребаем свое
if (!cur) cur = GetMaxCardWithOutPere();
// 3 пытаемс
if (!cur) cur = GetMaxCardWithOutPere();
if (!cur) cur = mCards.minFace();
}
// } else { //Side == LeftHand
// }
badlabel:
return cur;
}
///////////////////////////////////////////////////////////////////////////////
// misere catch, my move is second
Card *AiPlayer::MiserCatch2 (Card *aRightCard, Player *aLeftPlayer, Player *aRightPlayer) {
Card *cur = 0;
CardList aMaxCardList;
CardList *Naparnik;
eHand Side;
if (aRightPlayer->myGame() == g86) {
loadLists(aRightPlayer, aRightPlayer, aMaxCardList);
Naparnik = &(aLeftPlayer->mCards);
Side = RightHand;
} else {
loadLists(aLeftPlayer, aLeftPlayer, aMaxCardList);
Naparnik = &(aRightPlayer->mCards);
Side = LeftHand;
}
recalcPassOutTables(aMaxCardList, 23);
if (Side == LeftHand) {
// enemy is left
if (mCards.cardsInSuit(aRightCard->suit())) {
// у меня есть карты в данной масти
Card *MyMax = mCards.maxInSuit(aRightCard->suit());
//Card *MyMin = mCards.minInSuit(aRightCard->suit());
//Card *EnMax = aMaxCardList->maxInSuit(aRightCard->suit());
Card *EnMin = aMaxCardList.minInSuit(aRightCard->suit());
if (EnMin) {
// у противника есть карты в данной масти
if (*aRightCard < *EnMin) {
// можно попытаться всунуть
cur = mCards.lesserInSuit(EnMin);
if (!cur) cur = mCards.greaterInSuit(EnMin);
} else cur= mCards.greaterInSuit(EnMin);
} else cur = MyMax; // А вот тут надо смотреть кому нужен ход
} else {
// у меня нет карт в данной масти
if (mCardCarryThru) {
//надо пронести карту
if (mCards.exists(mCardCarryThru->face(),mCardCarryThru->suit())) {
cur = mCardCarryThru;
} else {
cur = mCards.maxInSuit(mCardCarryThru->suit());
if (!cur) cur = mCards.maxFace();
}
} else {
// указания на пронос - нет
cur = GetMaxCardPere();
if (!cur) cur = mCards.maxFace();
}
}
} else { // противник зашел под меня
Card *MyMax = mCards.maxInSuit(aRightCard->suit());
Card *MyMin = mCards.minInSuit(aRightCard->suit());
if (MyMax) {
if (*MyMin < *aRightCard) {
// if we both have lesser card in suit, or friend has nothing in
// this suit, enemy will take the trick
Card *NapMin = Naparnik->lesserInSuit(aRightCard);
Card *NapMax = Naparnik->greaterInSuit(aRightCard);
if (NapMin || !NapMax)
cur = mCards.lesserInSuit(aRightCard);
else
cur = MyMax; // кому передать код ?
} else cur = MyMax; // грохать ее самой большой
} else {
// а у меня нет масти
cur = GetMaxCardPere();
if (!cur) cur = mCards.maxFace();
}
}
mCardCarryThru = 0;
if (!cur) cur = mCards.minFace();
return cur;
}
///////////////////////////////////////////////////////////////////////////////
// misere catch, my move is third
Card *AiPlayer::MiserCatch3 (Card *aLeftCard, Card *aRightCard, Player *aLeftPlayer, Player *aRightPlayer) {
Card *cur = 0;
CardList aMaxCardList;
CardList *Naparnik;
eHand Side;
if (aRightPlayer->myGame() == g86) {
loadLists(aRightPlayer, aRightPlayer, aMaxCardList);
Naparnik = &(aLeftPlayer->mCards);
Side = RightHand;
printf("right is enemy");
} else {
loadLists(aLeftPlayer, aLeftPlayer, aMaxCardList);
Naparnik = &(aRightPlayer->mCards);
Side = LeftHand;
printf("left is enemy");
}
recalcPassOutTables(aMaxCardList, 23);
if (Side == LeftHand) { // Right player is my friend
if (mCards.cardsInSuit(aLeftCard->suit())) {
// у меня есть карты в данной масти
//Card *MyMax = mCards.maxInSuit(aLeftCard->suit());
//Card *MyMin = mCards.minInSuit(aLeftCard->suit());
if (*aLeftCard < *aRightCard) {
// напарник уже придавил карту
cur = mCards.maxInSuit(aLeftCard->suit());
} else {
//есть шанс всунуть
cur = mCards.lesserInSuit(aLeftCard);
if (!cur) cur = mCards.maxInSuit(aLeftCard->suit());
}
} else {
// у меня нет карт в данной масти
if (mCardCarryThru) {
//надо пронести карту
if (mCards.exists(mCardCarryThru->face(),mCardCarryThru->suit())) {
cur = mCardCarryThru;
} else {
cur = mCards.maxInSuit(mCardCarryThru->suit());
if (!cur) cur = mCards.maxFace();
}
} else {
// указания на пронос - нет
cur = GetMaxCardPere();
if (!cur) cur = mCards.maxFace();
}
}
} else { // Left player is my friend
Card *MyMax = mCards.maxInSuit(aLeftCard->suit());
Card *MyMin = mCards.minInSuit(aLeftCard->suit());
if (MyMax) {
if ((*MyMin < *aRightCard) && (aLeftCard->suit()==aRightCard->suit())) {
// push lesser card than enemy
cur = mCards.lesserInSuit(aRightCard);
if (!cur) cur = MyMax;
} else cur = MyMax; // грохать ее самой большой
} else {
// have no car of this suit
cur = GetMaxCardPere();
if (!cur) cur = mCards.maxFace();
}
}
mCardCarryThru = 0;
return cur;
}
///////////////////////////////////////////////////////////////////////////////
// game
///////////////////////////////////////////////////////////////////////////////
// game, my move is first
Card *AiPlayer::MyGame1 (Player *aLeftPlayer, Player *aRightPlayer) {
// 1-выбить козыря 2-разиграть масти с перехватами 3-без перехватов 4-???
Card *cur = 0;
eGameBid tmpGamesType = mMyGame;
CardList aMaxCardList;
int mast = mMyGame-(mMyGame/10)*10;
// набираем списки
loadLists(aLeftPlayer, aRightPlayer, aMaxCardList);
recalcTables(aMaxCardList, 1);
if (mLeft.cardsInSuit(mast) || mRight.cardsInSuit(mast)) {
// У противников есть козыря
cur = mCards.maxInSuit(mast);
if (!cur) cur = GetMaxCardWithOutPere(); // а у меня их нет !!!
if (!cur) cur = GetMaxCardPere(); //масть с перехватами (max)
if (!cur) cur = GetMinCardWithOutVz(); // лабуду
if (!cur) cur = mCards.maxFace();
} else {
// а козырьков у них и нету !!!
if (!cur) cur = GetMaxCardPere(); //масть с перехватами (max)
if (!cur) cur = GetMaxCardWithOutPere(); // и у меня их нет !!!
if (!cur) cur = GetMinCardWithOutVz(); // лабуду
if (!cur) cur = mCards.maxInSuit(mast);
if (!cur) cur = mCards.maxFace();
}
mMyGame = tmpGamesType;
return cur;
}
///////////////////////////////////////////////////////////////////////////////
// game, my move is second
Card *AiPlayer::MyGame2 (Card *aRightCard, Player *aLeftPlayer, Player *aRightPlayer) {
CardList aMaxCardList;
eGameBid tmpGamesType = mMyGame;
Card *cur = 0;
Card *MaxLeftCard = 0;
int mast = aRightCard->suit();
int koz = mMyGame-(mMyGame/10)*10;
// набираем списки
loadLists(aLeftPlayer, aRightPlayer, aMaxCardList);
recalcTables(aMaxCardList, 23);
cur = mCards.maxInSuit(mast);
if (!cur) {
// Нет Масти
if (!aLeftPlayer->mCards.cardsInSuit(mast)) {
// У левого тож нету
MaxLeftCard = aLeftPlayer->mCards.maxInSuit(koz); // k8: это заебись, а чо, если у нас нихуя козыря нет?
cur = mCards.greaterInSuit(MaxLeftCard); // k8: тогда тут тоже нет нихуя
if (!cur) cur = mCards.lesserInSuit(MaxLeftCard); // k8: и тут тоже нихуя
if (!cur) cur = GetMinCardWithOutVz(); // лабуду
if (!cur) cur = mCards.minFace();
} else {
// Есть масть у левого
cur = mCards.minInSuit(koz); // k8: это заебись, а чо, если у нас нихуя козыря нет?
// k8: копипасты?
if (!cur) cur = GetMinCardWithOutVz(); // лабуду
if (!cur) cur = mCards.minFace();
}
} else {
// У меня есть масть
if (aLeftPlayer->mCards.cardsInSuit(mast)) {
//У левого есть
MaxLeftCard = aLeftPlayer->mCards.maxInSuit(mast);
cur = mCards.greaterInSuit(MaxLeftCard);
if (!cur) cur = mCards.lesserInSuit(MaxLeftCard);
} else {
// У левого нет
if (!aLeftPlayer->mCards.cardsInSuit(koz)) {
// И козырей нет
cur = mCards.greaterInSuit(aRightCard);
if (!cur) cur = mCards.minInSuit(mast);
} else {
// есть у левого козыря
cur = mCards.minInSuit(mast);
}
}
}
mMyGame = tmpGamesType;
return cur;
}
///////////////////////////////////////////////////////////////////////////////
// game, my move is third
Card *AiPlayer::MyGame3 (Card *aLeftCard, Card *aRightCard, Player *aLeftPlayer, Player *aRightPlayer) {
Card *cur = 0;
Card *maxInSuit;
eGameBid tmpGamesType = mMyGame;
CardList aMaxCardList;
int mast = mMyGame-(mMyGame/10)*10;
// набираем списки
loadLists(aLeftPlayer, aRightPlayer, aMaxCardList);
recalcTables(aMaxCardList, 23);
if (mCards.cardsInSuit(aLeftCard->suit())) {
// у меня есть масть, в которую зашел левый
if (aLeftCard->suit() == aRightCard->suit()) {
// постараемся ударить
cur = mCards.greaterInSuit(aLeftCard);
if (!cur) cur = mCards.minInSuit(aLeftCard->suit());
} else { //aLeftCard->suit() == aRightCard->suit()
if (aRightCard->suit() != mast) {
// не бита козырем
cur = mCards.greaterInSuit(aLeftCard);
if (!cur) cur = mCards.minInSuit(aLeftCard->suit());
} else {
// бита козырем, мне не надо бить
cur = mCards.minInSuit(aLeftCard->suit());
}
}
} else {
// у меня нет масти в которую зашел левый
if (aLeftCard->suit() == aRightCard->suit()) {
//k8:? bug?
//if (*aLeftCard > *aRightCard) maxInSuit = aLeftCard; else maxInSuit = aLeftCard;
if (*aLeftCard > *aRightCard) maxInSuit = aLeftCard; else maxInSuit = aRightCard;
} else {
if (aLeftCard->suit() != mast && aRightCard->suit() != mast) maxInSuit = aLeftCard;
else maxInSuit = aRightCard;
}
cur = mCards.greaterInSuit(maxInSuit);
if (!cur) cur = mCards.minInSuit(mast);
if (!cur) cur = GetMinCardWithOutVz(); // нет коз.
if (!cur) cur = mCards.minFace();
}
mMyGame = tmpGamesType;
return cur;
}
///////////////////////////////////////////////////////////////////////////////
// whist
///////////////////////////////////////////////////////////////////////////////
// мой вист или пас 1 заход - мой
Card *AiPlayer::MyWhist1 (Player *aLeftPlayer, Player *aRightPlayer) {
// 1 - выбить козыря 2-разиграть масти с перехватами 3-без перехватов 4-???
Card *cur = 0;
eGameBid tmpGamesType = mMyGame;
CardList aMaxCardList;
Player *aEnemy, *aFriend;
int mast;
// Кто игрок а кто напарник
if (aLeftPlayer->myGame() != gtPass && aLeftPlayer->myGame() != whist) {
aEnemy = aLeftPlayer;
aFriend = aRightPlayer;
} else {
aEnemy = aRightPlayer;
aFriend = aLeftPlayer;
}
mast = aEnemy->myGame()-(aEnemy->myGame()/10)*10;
// набираем списки
//loadLists(aLeftPlayer,aRightPlayer,aMaxCardList);
//recalcTables(aMaxCardList,1);
if (aEnemy == aLeftPlayer) {
// Слева игрок
loadLists(aLeftPlayer, aLeftPlayer, aMaxCardList);
recalcTables(aMaxCardList, 1);
if (aLeftPlayer->mCards.cardsInSuit(mast) <= 2) {
Card *m = mCards.maxInSuit(mast);
if (!m) cur = mCards.minInSuit(aLeftPlayer->mCards.emptySuit (mast));
else if (aLeftPlayer->mCards.maxInSuit(mast)->face() < m->face()) cur = mCards.maxInSuit(mast);
else cur = mCards.minInSuit(aLeftPlayer->mCards.emptySuit(mast));
} else {
cur = mCards.minInSuit(aLeftPlayer->mCards.emptySuit (mast));
}
if (!cur) cur = GetMinCardWithOutVz();
/*
if ( mCards.exists(FACE_ACE,cur->suit()) || mCards.exists(FACE_KING,cur->suit())) {
cur = 0;
cur = mCards.minInSuit(aMaxCardList->emptySuit(0));
}
*/
if (!cur) cur = GetMaxCardWithOutPere();
if (!cur) cur = mCards.minInSuit(mast);
if (!cur) cur = GetMaxCardPere();
} else {
// слева - напарник
loadLists(aRightPlayer, aRightPlayer, aMaxCardList);
recalcTables(aMaxCardList, 1);
cur = GetMaxCardWithOutPere();
if (!cur) cur = GetMaxCardPere();
if (!cur) cur = mCards.maxFace();
}
mMyGame = tmpGamesType;
return cur;
}
///////////////////////////////////////////////////////////////////////////////
// мой вист или пас 2 заход - мой
Card *AiPlayer::MyWhist2 (Card *aRightCard, Player *aLeftPlayer, Player *aRightPlayer) {
Card *cur = 0;
eGameBid tmpGamesType = mMyGame;
CardList aMaxCardList;
Player *aEnemy, *aFriend;
int mast;
// Кто игрок а кто напарник
if (aLeftPlayer->myGame() != gtPass && aLeftPlayer->myGame() != whist) {
aEnemy = aLeftPlayer;
aFriend = aRightPlayer;
} else {
aEnemy = aRightPlayer;
aFriend = aLeftPlayer;
}
mast = aEnemy->myGame()-(aEnemy->myGame()/10)*10;
// набираем списки
if (aEnemy == aLeftPlayer) {
// Слева игрок
loadLists(aLeftPlayer, aLeftPlayer, aMaxCardList);
recalcTables(aMaxCardList, 23);
// Ну если он заходил под вистуза с туза
if ( aRightCard->face() >= 10 ) cur = mCards.minInSuit(aRightCard->suit());
else cur = mCards.maxInSuit(aRightCard->suit()); // может умный и больше заходов у него нет в данную масть а есть козырь
if (!cur) cur = mCards.maxInSuit(mast); // а у меня масти и нет !!! прибъем максимальной
if (!cur) cur = GetMinCardWithOutVz();
} else {
// слева - напарник
loadLists(aRightPlayer, aRightPlayer, aMaxCardList);
recalcTables(aMaxCardList, 23);
cur = mCards.greaterInSuit(aRightCard);
if (!cur) cur = mCards.minInSuit(aRightCard->suit());
if (!cur) cur = mCards.minInSuit(mast); // Нет масти пробуем козырь
if (!cur) cur = GetMinCardWithOutVz(); // Нет масти и козыря
}
mMyGame = tmpGamesType;
return cur;
}
///////////////////////////////////////////////////////////////////////////////
// мой вист или пас 3 заход - мой
Card *AiPlayer::MyWhist3 (Card *aLeftCard, Card *aRightCard, Player *aLeftPlayer, Player *aRightPlayer) {
Card *cur = 0;
Card *maxInSuit;
eGameBid tmpGamesType = mMyGame;
CardList aMaxCardList;
Player *aEnemy, *aFriend;
int mast;
// Кто игрок а кто напарник
if (aLeftPlayer->myGame() != gtPass && aLeftPlayer->myGame() != whist) {
aEnemy = aLeftPlayer;
aFriend = aRightPlayer;
} else {
aEnemy = aRightPlayer;
aFriend = aLeftPlayer;
}
mast = aEnemy->myGame()-(aEnemy->myGame()/10)*10;
// набираем списки
//loadLists(aLeftPlayer,aRightPlayer,aMaxCardList);
//recalcTables(aMaxCardList,23);
if (mCards.cardsInSuit(aLeftCard->suit())) {
// у меня есть масть в которую зашел левый
if (aEnemy == aLeftPlayer) {
// левый - вражина
loadLists(aLeftPlayer, aLeftPlayer, aMaxCardList);
recalcTables(aMaxCardList, 23);
if (aLeftCard->suit() == aRightCard->suit()) {
if (*aRightCard > *aLeftCard) {
// бить не надо
cur = mCards.minInSuit(aRightCard->suit());
} else {
// постараемсмя ударить
cur = mCards.greaterInSuit(aLeftCard);
if (!cur) cur = mCards.minInSuit(aLeftCard->suit());
}
} else { //aLeftCard->suit() == aRightCard->suit()
if (aRightCard->suit() != mast) {
// не бита козырем
cur = mCards.greaterInSuit(aLeftCard);
if (!cur) cur = mCards.minInSuit(aLeftCard->suit());
} else {
// бита козырем, мне не надо бить
cur = mCards.minInSuit(aLeftCard->suit());
}
}
} else {
//правый вражииина
loadLists(aRightPlayer, aRightPlayer, aMaxCardList);
recalcTables(aMaxCardList, 23);
if (aLeftCard->suit() == aRightCard->suit()) {
if (*aRightCard > *aLeftCard) {
// попытаться прибить правого
cur = mCards.greaterInSuit(aRightCard);
if (!cur) cur = mCards.minInSuit(aRightCard->suit());
} else {
// бить не надо
cur = mCards.minInSuit(aRightCard->suit());
}
} else {
if (aRightCard->suit() == mast) {
// левый зашел, а правый пригрел козырем
cur = mCards.minInSuit(aLeftCard->suit());
} else {
// Ух ты .... Левый друг зашел а правый пронес ерунду !!!
cur = mCards.minInSuit(aLeftCard->suit());
}
}
}
} else {
// у меня нет масти в которую зашел левый
if (aLeftCard->suit() == aRightCard->suit()) {
//k8: wtf?
//if (*aLeftCard > *aRightCard) maxInSuit = aLeftCard; else maxInSuit = aLeftCard;
if (*aLeftCard > *aRightCard) maxInSuit = aLeftCard; else maxInSuit = aRightCard;
} else {
if (aLeftCard->suit() != mast && aRightCard->suit() != mast) maxInSuit = aLeftCard;
else maxInSuit = aRightCard;
}
if (aEnemy == aLeftPlayer) {
// Слева игрок
loadLists(aLeftPlayer, aLeftPlayer, aMaxCardList);
recalcTables(aMaxCardList, 23);
if (maxInSuit == aLeftCard) {
// попытаемся хлопнуть его карту
cur = mCards.greaterInSuit(aLeftCard);
} else {
// Уже наша взятка... скидываем минимальную
cur = mCards.minInSuit(maxInSuit->suit());
}
} else {
// слева - напарник
loadLists(aRightPlayer, aRightPlayer, aMaxCardList);
recalcTables(aMaxCardList, 23);
if (maxInSuit == aLeftCard) {
// Уже наша взятка... скидываем минимальную
cur = mCards.minInSuit(maxInSuit->suit());
} else {
//попытаемся хлопнуть его карту
cur = mCards.greaterInSuit(aLeftCard);
}
}
if (!cur) cur = mCards.minInSuit(mast);
if (!cur) cur = GetMinCardWithOutVz(); // нет коз.
if (!cur) cur = mCards.minFace();
}
mMyGame = tmpGamesType;
return cur;
}
///////////////////////////////////////////////////////////////////////////////
// pass-outs
///////////////////////////////////////////////////////////////////////////////
// my passout first
Card *AiPlayer::MyPass1 (Card *rMove, Player *aLeftPlayer, Player *aRightPlayer) {
Card *cur = 0;
eGameBid tmpGamesType = mMyGame;
CardList aMaxCardList;
CardList aTmpList, aStackStore;
int doRest = 0;
if (rMove != 0) {
cur = mCards.minInSuit(rMove->suit());
return cur;
/*aTmpList.copySuit(&mCards, (eSuit)rMove->suit());
aStackStore = mCards;
mCards = aTmpList;
doRest = 1;*/
//loadLists(aLeftPlayer, aRightPlayer, aMaxCardList); // !!!!!!!!!
//recalcPassOutTables(aMaxCardList, 1);
}
if (tmpGamesType == raspass || tmpGamesType == g86) { // распасы/мизер
loadLists(aLeftPlayer, aRightPlayer, aMaxCardList); // !!!!!!!!!
recalcPassOutTables(aMaxCardList,1);
// тема такая : 100 % отбери своё, если такового нет - мах в минимально длинной масти
/*cur = GetMaxCardWithOutPere(); // за искл тех случ коды масти уже нет
if (cur) {
if (aLeftPlayer->mCards.cardsInSuit(cur->suit()) == 0 &&
aRightPlayer->mCards.cardsInSuit(cur->suit()) == 0) {
cur = 0;
}
}*/
//if (!cur) cur = GetMaxCardPere(); //масть с перехватами (max)
//if (!cur) cur = GetMinCardWithOutVz(); // лабуду
// Randomization
int suit[4];
int s;
for (int i=0; i<4; i++) {
s=0;
while (s==0) {
s = qrand()%4+1;
for (int j=0; jmCards.greaterInSuit(cur) != 0 ||
aRightPlayer->mCards.greaterInSuit(cur) != 0)
return cur;
else
cur = 0;
}
if (!cur) cur = mCards.minFace();
}
//if (doRest) mCards = aStackStore;
//mMyGame = tmpGamesType;
return cur;
}
///////////////////////////////////////////////////////////////////////////////
// my passout second
Card *AiPlayer::MyPass2 (Card *aRightCard, Player *aLeftPlayer, Player *aRightPlayer) {
Card *cur = 0;
eGameBid tmpGamesType = mMyGame;
int mast = aRightCard->suit();
CardList aMaxCardList;
loadLists(aLeftPlayer, aRightPlayer, aMaxCardList);
recalcPassOutTables(aMaxCardList, 1);
/////////////////////////////////////////////////////////
if (tmpGamesType == raspass || tmpGamesType == g86) {
// распасы/мизер
cur = mCards.maxInSuit(mast);
if (!cur) {
// Нет Масти
// во шара !!! Льем мах в масти где есть 100% взятки
cur = GetMaxCardWithOutPere();
if (!cur) cur = GetMaxCardPere(); //масть с перехватами (max)
if (!cur) cur = GetMinCardWithOutVz(); // лабуду
if (!cur) cur = mCards.minFace();
} else {
// У меня есть масть
if (aLeftPlayer->mCards.cardsInSuit(mast)) {
//У левого есть
cur = mCards.lesserInSuit(aLeftPlayer->mCards.minInSuit(mast));
if (!cur) cur = mCards.lesserInSuit(aRightCard);
if (!cur) cur = mCards.maxInSuit(mast);
} else {
// У левого нет
cur = mCards.lesserInSuit(aRightCard);
if (!cur) cur = mCards.maxInSuit(mast);
}
}
}
/////////////////////////////////////////////////////////
mMyGame = tmpGamesType;
return cur;
}
///////////////////////////////////////////////////////////////////////////////
// my passout third
Card *AiPlayer::MyPass3 (Card *aLeftCard, Card *aRightCard, Player *aLeftPlayer, Player *aRightPlayer) {
Card *cur=0;
/*Card *maxInSuit;*/
eGameBid tmpGamesType = mMyGame;
CardList aMaxCardList;
//int mast = mMyGame-(mMyGame/10)*10;
// набираем списки
loadLists(aLeftPlayer, aRightPlayer, aMaxCardList);
recalcPassOutTables(aMaxCardList, 23);
if (mCards.cardsInSuit(aLeftCard->suit())) {
// у меня есть масть в которую зашел левый
// постараемсмя пропустить
if (aLeftCard->suit() == aRightCard->suit()) {
if (*aRightCard > *aLeftCard) cur = mCards.lesserInSuit(aRightCard);
else cur = mCards.lesserInSuit(aLeftCard);
} else cur = mCards.lesserInSuit(aLeftCard);
if (!cur) cur = mCards.maxInSuit(aLeftCard->suit());
} else {
// у меня нет масти в которую зашел левый
cur = GetMaxCardWithOutPere();
if (!cur) cur = GetMaxCardPere(); //масть с перехватами (max)
if (!cur) cur = GetMinCardWithOutVz(); // лабуду
if (!cur) cur = mCards.minFace();
}
mMyGame = tmpGamesType;
return cur;
}
///////////////////////////////////////////////////////////////////////////////
// game moves
///////////////////////////////////////////////////////////////////////////////
// make game move (dispatcher)
Card *AiPlayer::moveSelectCard (Card *lMove, Card *rMove, Player *aLeftPlayer, Player *aRightPlayer, bool isPassOut) {
Q_UNUSED(isPassOut)
printf ("AiPlayer (%d) moves\n", mPlayerNo);
Card *cur = 0;
if (lMove == 0 && rMove == 0) {
// мой заход - первый
if (mMyGame == gtPass || mMyGame == whist) cur = MyWhist1(aLeftPlayer, aRightPlayer); // кто-то играет а я как бы вистую
else if (mMyGame == g86catch) cur = MiserCatch1(aLeftPlayer, aRightPlayer);
else if (mMyGame == g86) cur = Miser1(aLeftPlayer,aRightPlayer);
else if (mMyGame == raspass) cur = MyPass1(rMove, aLeftPlayer, aRightPlayer); // ну типа распасы или мизер
else cur = MyGame1(aLeftPlayer, aRightPlayer); // ну типа моя игра
}
if (lMove == 0 && rMove != 0) {
// мой заход - второй
if (mMyGame == gtPass || mMyGame == whist) cur = MyWhist2(rMove, aLeftPlayer, aRightPlayer); // кто-то играет а я как бы вистую
else if (mMyGame == g86catch) cur = MiserCatch2(rMove, aLeftPlayer, aRightPlayer);
else if (mMyGame == g86) cur = Miser2(rMove, aLeftPlayer, aRightPlayer);
else if (mMyGame == raspass) cur = MyPass2(rMove, aLeftPlayer, aRightPlayer); // ну типа распасы или мизер
else cur = MyGame2(rMove, aLeftPlayer, aRightPlayer); // ну типа моя игра
}
if (lMove != 0 && rMove != 0) {
// мой заход - 3
if (mMyGame == gtPass || mMyGame == whist ) cur = MyWhist3(lMove, rMove, aLeftPlayer, aRightPlayer); // кто-то играет а я как бы вистую
else if (mMyGame == g86catch) cur = MiserCatch3(lMove, rMove, aLeftPlayer, aRightPlayer);
else if (mMyGame == g86) cur = Miser3(lMove, rMove, aLeftPlayer, aRightPlayer);
else if (mMyGame == raspass) cur = MyPass3(lMove, rMove, aLeftPlayer, aRightPlayer); // ну типа распасы или мизер
else cur = MyGame3(lMove, rMove, aLeftPlayer, aRightPlayer); // ну типа моя игра
}
mCards.remove(cur);
mCardsOut.insert(cur);
return cur;
}
///////////////////////////////////////////////////////////////////////////////
// Pass or Whist or Halfwhist
eGameBid AiPlayer::moveFinalBid (eGameBid MaxGame, int HaveAWhist, int nGamerPass) {
Q_UNUSED(nGamerPass)
eGameBid Answer;
eGameBid MyMaxGame = moveCalcDrop();
int vz = MyMaxGame/10;
if (MaxGame == g86) {
Answer = g86catch; // Misere
goto myGame;
}
if (optStalingrad && MaxGame == g61) {
Answer = whist; // Stalingrad
goto myGame;
}
if (!opt10Whist && MaxGame>=101 && MaxGame<=105) {
Answer = whist;
goto myGame;
}
if (HaveAWhist == gtPass)
Answer = (vz > gameWhistsMin(MaxGame)) ? whist : gtPass;
else
Answer = (vz > gameWhists(MaxGame)) ? whist : gtPass;
//Answer = (HaveAWhist != whist && vz >= gameWhistsMin(MaxGame)) ? whist : gtPass ;
//if (HaveAWhist == gtPass && vz < gameWhistsMin(MaxGame)) Answer = gtPass;
myGame:
if ((Answer == gtPass) && (nGamerPass == 1))
Answer = halfwhist;
mMyGame = Answer;
return Answer;
}
///////////////////////////////////////////////////////////////////////////////
// calc drop
eGameBid AiPlayer::moveCalcDrop () {
eGameBid GamesTypeRetVal;
int f;
int nMaxMastLen = 0;
eSuit nMaxMast = SuitNone;
tSuitProbs LocalMastTable[5];
LocalMastTable[0].tricks = 0;
LocalMastTable[0].perehvatov = 0;
LocalMastTable[0].sum = 0;
for (f = 1; f <= 4; f++) {
LocalMastTable[f] = countGameTricks((eSuit)f, 1);
LocalMastTable[0].tricks += LocalMastTable[f].tricks;
LocalMastTable[0].perehvatov +=LocalMastTable[f].perehvatov;
LocalMastTable[0].sum += LocalMastTable[f].sum;
}
for (f = 1; f <= 4; f++) {
// предполагаемый козырь - самая длинная масть
if (mCards.cardsInSuit(f) > nMaxMastLen) {
nMaxMastLen = mCards.cardsInSuit(f);
nMaxMast = (eSuit)f;
}
}
for (f = 1; f <= 4; f++) {
if (mCards.cardsInSuit(f) == nMaxMastLen && nMaxMast != f) {
// есть максимально длинные масти
if (LocalMastTable[f].sum > LocalMastTable[nMaxMast].sum) nMaxMast = (eSuit)f;
}
}
//масть и звятки уже посчитали
GamesTypeRetVal = (eGameBid)(LocalMastTable[0].tricks*10+nMaxMast);
// это то, что мы можем играть максимально
return GamesTypeRetVal;
}
///////////////////////////////////////////////////////////////////////////////
//
eGameBid AiPlayer::dropForMisere () {
Card *FirstCardOut = 0, *SecondCardOut = 0;
Card *tmpFirstCardOut, *tmpSecondCardOut;
Card *RealFirstCardOut, *RealSecondCardOut;
eGameBid Hight = g105, tmpHight = g105;
for (int f = 0; f < 12; f++) {
tmpFirstCardOut = mCards.at(f);
mCards.removeAt(f);
//for ( int j=0;j<12;j++ ) {
for (int j = f+1; j < 12; j++) { // patch from Rasskazov K. (kostik450@mail.ru)
if (j != f) {
tmpSecondCardOut = mCards.at(j);
mCards.removeAt(j);
AiPlayer *tmpGamer = new AiPlayer(99);
tmpGamer->mCards = mCards;
tmpGamer->mCards.mySort();
tmpHight = tmpGamer->moveCalcDrop();
if ((tmpHight < Hight) ||
(tmpHight == Hight && tmpGamer->mSuitProb[0].perehvatov < mSuitProb[0].perehvatov)) {
Hight = tmpHight;
FirstCardOut = tmpFirstCardOut;
SecondCardOut = tmpSecondCardOut;
}
delete tmpGamer;
mCards.putAt(j, tmpSecondCardOut);
}
}
mCards.putAt(f, tmpFirstCardOut);
}
RealFirstCardOut = mCards.maxInSuit(FirstCardOut->suit());
mCards.remove(RealFirstCardOut);
mOut.insert(RealFirstCardOut);
if (SecondCardOut->suit() != FirstCardOut->suit()) {
RealSecondCardOut = mCards.maxInSuit(SecondCardOut->suit());
} else {
RealSecondCardOut = mCards.greaterInSuit(FirstCardOut);
if (!RealSecondCardOut) RealSecondCardOut = mCards.maxFace(); // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!1 Bad algoritm
}
mCards.remove(RealSecondCardOut);
mOut.insert(RealSecondCardOut);
mCards.mySort();
return g86;
}
///////////////////////////////////////////////////////////////////////////////
//
eGameBid AiPlayer::dropForGame () {
Card *FirstCardOut = 0, *SecondCardOut = 0;
Card *tmpFirstCardOut, *tmpSecondCardOut;
Card *RealFirstCardOut, *RealSecondCardOut;
eGameBid Hight = zerogame, tmpHight = zerogame;
for (int f = 0; f < 12; f++) {
tmpFirstCardOut = mCards.at(f);
mCards.removeAt(f);
for (int j = 0; j < 12; j++) {
if (j != f) {
tmpSecondCardOut = mCards.at(j);
mCards.removeAt(j);
AiPlayer *tmpGamer = new AiPlayer(99);
tmpGamer->mCards = mCards;
tmpGamer->mCards.mySort();
tmpHight = tmpGamer->moveCalcDrop();
if ((tmpHight > Hight) ||
(tmpHight == Hight && tmpGamer->mSuitProb[0].perehvatov < mSuitProb[0].perehvatov)) {
Hight = tmpHight;
FirstCardOut = tmpFirstCardOut;
SecondCardOut = tmpSecondCardOut;
}
tmpGamer->mCards.clear();
delete tmpGamer;
mCards.putAt(j, tmpSecondCardOut);
}
}
mCards.putAt(f, tmpFirstCardOut);
}
RealFirstCardOut = mCards.minInSuit(FirstCardOut->suit());
mCards.remove(RealFirstCardOut);
mOut.insert(RealFirstCardOut);
if (SecondCardOut->suit() != FirstCardOut->suit()) {
RealSecondCardOut = mCards.minInSuit(SecondCardOut->suit());
} else {
RealSecondCardOut = mCards.greaterInSuit(FirstCardOut);
if (!RealSecondCardOut) RealSecondCardOut = mCards.minFace(); // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!1 Bad algoritm
}
mCards.remove(RealSecondCardOut);
mOut.insert(RealSecondCardOut);
mCards.mySort();
//Hight = moveBidding(undefined,undefined);
Hight = moveCalcDrop();
if (Hight < mMyGame) {
// Вот такая ерунда
int tmpvz = Hight/10, tmpmast = Hight-tmpvz*10;
while (tmpHight < mMyGame) {
tmpvz++;
tmpHight = (eGameBid)(tmpvz*10+tmpmast);
}
mMyGame = tmpHight;
} else {
mMyGame = Hight;
}
return mMyGame;
}
//ход при торговле
eGameBid AiPlayer::moveBidding (eGameBid lMove, eGameBid rMove) {
//mIStart = (lMove == undefined && rMove == undefined);
//qDebug() << mPlayerNo << mIStart;
/*
if ( mMyGame == gtPass ) {
mMyGame=gtPass;
} else {
*/
//mMyGame = gtPass;
if (mMyGame != gtPass) {
int f;
int nMaxMastLen = 0;
eSuit nMaxMast = SuitNone;
tSuitProbs LocalMastTable[5];
/*
if (optAggPass && optPassCount > 0) {
if (lMove == undefined) lMove = g71;
if (rMove == undefined) rMove = g71;
}
*/
eGameBid curMaxGame = qMax(lMove, rMove);
if (optAggPass && optPassCount > 0) {
if (curMaxGame < g71) curMaxGame = g65;
if (lMove != gtPass && lMove != undefined && lMove < g65) lMove = g65;
if (rMove != gtPass && rMove != undefined && rMove < g65) rMove = g65;
}
LocalMastTable[0].tricks=0;
LocalMastTable[0].perehvatov=0;
LocalMastTable[0].sum = 0;
for (f = 1; f <= 4; f++) {
LocalMastTable[f] = countGameTricks((eSuit)f, 1);
LocalMastTable[0].tricks += LocalMastTable[f].tricks;
LocalMastTable[0].perehvatov +=LocalMastTable[f].perehvatov;
LocalMastTable[0].sum += LocalMastTable[f].sum;
}
// предполагаемый козырь -- самая длинная масть
for (f = 1; f <= 4; f++) {
if (mCards.cardsInSuit(f) > nMaxMastLen) {
nMaxMastLen = mCards.cardsInSuit(f);
nMaxMast = (eSuit)f;
}
}
for (f = 1; f <= 4; f++) {
if (mCards.cardsInSuit(f) == nMaxMastLen && nMaxMast != f) {
// есть максимально длинные масти
if (LocalMastTable[f].sum > LocalMastTable[nMaxMast].sum) nMaxMast = (eSuit)f;
}
}
// масть и взятки уже посчитали
if (curMaxGame <= g75) {
mMyGame = (eGameBid)((LocalMastTable[0].tricks+1)*10+nMaxMast);
} else {
mMyGame = (eGameBid)((LocalMastTable[0].tricks)*10+nMaxMast);
}
// if first move or one player passed
if ((rMove == gtPass || rMove == undefined) && (lMove == gtPass || lMove == undefined)) {
if (LocalMastTable[0].tricks >= 4) {
/*if (optAggPass && optPassCount > 0) mMyGame = g71;
else*/ mMyGame = g61;
} else {
if (LocalMastTable[0].tricks == 0) {
// check for misere !!!
mMyGame = checkForMisere() ? g86 : gtPass ;
} else mMyGame = gtPass;
}
}
else if (mMyGame >= curMaxGame){
if ((mIStart) && (mMyGame < succBid(curMaxGame)))
mMyGame = curMaxGame;
else
mMyGame = (eGameBid)succBid(curMaxGame);
if (optAggPass && (optPassCount > 0) && (mMyGame < g71))
mMyGame = g71;
}
else
mMyGame = gtPass;
/*
if( mMyGame >= curMaxGame ) {
mMyGame = (eGameBid) succBid(curMaxGame);
} else {
}*/
// это то, что мы можем играть максимально
/*if ( mMyGame > gtPass ) {
if ( rMove < lMove ) {
if ( lMove <= mMyGame ) {
if ( lMove!=g61 )
mMyGame = lMove; // say here
else
mMyGame = (eGameBid) succBid(lMove);
} else {
mMyGame = gtPass;
}
} else { // rMove > lMove
if ( mMyGame > rMove ) {
// asm int 3;
if (rMove!=undefined) {
mMyGame = (eGameBid) succBid(rMove);
} else {
mMyGame = g61;
}
} else {
mMyGame = gtPass;
}
}
} else { // mMyGame > gtPass
if ( (rMove==gtPass || rMove==undefined) && ( lMove==gtPass || lMove==undefined ) ) {
if ( LocalMastTable[0].tricks >= 4 ) {
mMyGame = g61;
} else {
if ( LocalMastTable[0].tricks == 0 ) {
// check for miser !!!
if (checkForMisere()) {
mMyGame = g86;
} else {
mMyGame = gtPass;
}
} else {
mMyGame = gtPass;
}
}
} else {
mMyGame = gtPass;
}
}*/
}
//???
if (optAggPass && optPassCount > 0 && mMyGame != gtPass && mMyGame < g71) {
moveBidding(g71, g71);
// if (optAggPass && optPassCount > 0 && mMyGame != gtPass && mMyGame < g71) moveBidding(g72, g72);
}
return mMyGame;
}
//-----------------------------------------------------------------------
/*
void AiPlayer::makestatfill () {
eHand lr = LeftHand;
for (int m = 1; m <= 4; m++) {
for (int c = FACE_ACE; c >= 7; c--) {
if (!mCards.exists(c, m)) {
if (lr == LeftHand) {
mLeft.insert(newCard(c, m));
lr = RightHand;
} else {
mRight.insert(newCard(c, m));
lr = LeftHand;
}
}
}
}
}
*/
//-----------------------------------------------------------------------
/*
void AiPlayer::makestatfill (int nCards, int maxmin) {
int nCounter = 0;
eHand lr = LeftHand;
if (maxmin == 1) {
for (int m = 1; m <= 4; m++) {
for (int c = FACE_ACE; c >= 7; c--) {
if (!mCards.exists(c, m) && !mOut.exists(c, m)) {
if (lr == LeftHand) {
mLeft.insert(newCard(c, m));
lr = RightHand;
} else {
mRight.insert(newCard(c, m));
lr = LeftHand;
nCounter++;
if (nCounter >= nCards) return;
}
}
}
}
} else {
for (int m = 1; m <= 4; m++) {
for (int c = 7; c <= FACE_ACE; c++) {
if (!mCards.exists(c, m) && !mOut.exists(c, m)) {
if (lr == LeftHand) {
mLeft.insert(newCard(c, m));
lr = RightHand;
} else {
mRight.insert(newCard(c, m));
lr = LeftHand;
nCounter++;
if (nCounter >= nCards) return;
}
}
}
}
}
}
*/
bool AiPlayer::chooseClosedWhist () {
//tSuitProbs countGameTricks((eSuit)f, 1)
if (qrand()%4 == 0)
return true;
else
return false;
}
openpref-0.1.3/src/logic/aialphabeta.cpp 0000755 0001750 0001750 00000054660 11265177055 017611 0 ustar kostya kostya /*
* OpenPref - cross-platform Preferans game
*
* Copyright (C) 2000-2009 OpenPref Developers
* (see file AUTHORS for more details)
* Contact: annulen@users.sourceforge.net
*
* OpenPref is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (see file COPYING); if not, see
* http://www.gnu.org/licenses
*/
#include
#include
#include
#include
#include "prfconst.h"
#include "formbid.h"
#include "kpref.h"
#include "debug.h"
#include "deskview.h"
#include "player.h"
#include "card.h"
#include "cardlist.h"
#include "ncounter.h"
#include "plscore.h"
#include "aialphabeta.h"
// 1-33; 0: unused
/*
#define SUIT(c) (((c)-1)%4)
#define FACE(c) ((((c)-1)/4)+7)
#define CARD(face,suit) (((face-7)*4+(suit))+1)
*/
typedef unsigned char card_t;
static inline card_t CARD (int face, int suit) {
if (face < 7 || face > 14 || suit < 0 || suit > 3) abort();
return ((face-7)*4+suit)+1;
}
static inline int SUIT (int c) {
return (c-1)%4;
}
static inline int FACE (int c) {
return ((c-1)/4)+7;
}
static inline int compareCards (int c0, int c1) {
int t0 = SUIT(c0), t1 = SUIT(c1);
int r = t1-t0;
if (!r) {
t0 = FACE(c0), t1 = FACE(c1);
r = t0-t1;
}
return r;
}
void xsortCards (card_t *arr, int len) {
int f, c;
for (f = 0; f < len; f++) {
for (c = len-1; c > f; c--) {
int cc = compareCards(arr[c], arr[f]);
if (cc > 0) {
int t = arr[c];
arr[c] = arr[f];
arr[f] = t;
}
}
}
}
static int gTrumpSuit; // trump; global var
static int gPassOutSuit; // нужная масть для первого или второго круга распасов
//static int gGameBid; // >=6
//static int gMoves[4][10];
//static int gTricks[3];
//static int gE0, gE1, gMe;
//static int gWhoPlays;
static int gIterations;
//static int gTrk = 0;
static bool gPassOut;
typedef struct {
int faces[10];
int suits[10];
int suitCount[4]; // # of cards in each suit
int suitStart[4]; // 1st card of each suit
int tricks;
} tHand;
//static long long xStTime, cTime;
static tHand xHands[3];
static int xCardsLeft;
static int xDeskFaces[3], xDeskSuits[3];
//static int lastMoveF, lastMoveS;
static QTime stTime;
//#define ABDEBUG
//#define ADVANCED_RES
/*
* карты должны быть отсортированы по мастям в порядке убывания "морды"
* a: игрок player набрал максимум вот столько
* b: игрок player+1 набрал максимум вот столько
* c: игрок player+2 набрал максимум вот столько
* возврат: то же самое
*
* идея и псевдокод взяты отсюда: http://clauchau.free.fr/gamma.html
* idea and pseudocode was taken from here: http://clauchau.free.fr/gamma.html
*/
static void abcPrune (
int turn, int player,
int a, int b, int c,
int *ra, int *rb, int *rc, int *rm
) {
/*
* (x, y, z) := some static additive evaluation of Position,
* x measuring how good is Position for the Player to move,
* y measuring how good is Position for the next Player,
* z measuring how good is Position for the further next Player,
* the higher the better, -infinite for a defeat, +infinite for a win;
*
* if the game is over then return (x, y, z, "game over");
* else return ( min(x-y, x-z), min(y-x, y-z), min(z-x, z-y), "static" );
*/
/*
if (!xCardsLeft) {
gIterations++;
if (gIterations%8000000 == 0) {
cTime = getTimeMs();
fprintf(stderr, "\r%i (%i seconds)\x1b[K", gIterations, (int)((cTime-xStTime)/1000));
}
*ra = xHands[player].tricks;
*rb = xHands[(player+1)%3].tricks;
*rc = xHands[(player+2)%3].tricks;
return;
}
*/
//int lmF = lastMoveF, lmS = lastMoveS;
#ifdef ABDEBUG
printf("cards left: %i; turn: %i\n", xCardsLeft, turn);
printStatus(turn, player, 0);
#endif
tHand *hand = &(xHands[player]);
//int bestx = a, worsty = b, worstz = c;
int bestx = -666, worsty = 666, worstz = 666;
int bestm = -1;
int n = 0; // will count equivalent moves
int crdFace, crdSuit, tmp, who = -1;
int newTurn = turn+1, newPlayer = (player+1)%3;
int sDeskFaces[3], sDeskSuits[3];
sDeskFaces[0] = xDeskFaces[0]; sDeskFaces[1] = xDeskFaces[1]; sDeskFaces[2] = xDeskFaces[2];
sDeskSuits[0] = xDeskSuits[0]; sDeskSuits[1] = xDeskSuits[1]; sDeskSuits[2] = xDeskSuits[2];
if (turn == 2) {
newTurn = 0;
--xCardsLeft;
}
int crdNo = 0, crdNext, ccc = 0;
for (int f = 0; f < 10; f++) if (hand->faces[f]) ccc++;
if (!ccc) {
abort();
}
//int movesChecked = 0, firstm = -1;
while (crdNo < 10) {
crdFace = hand->faces[crdNo];
if (!hand->faces[crdNo]) {
crdNo++;
continue;
}
crdNext = crdNo+1;
crdSuit = hand->suits[crdNo];
if (!turn) {
// первый ход может быть любой ваще, если это не первый и не второй круг распасов
if (gPassOutSuit >= 0 && crdSuit != gPassOutSuit && hand->suitCount[gPassOutSuit]) {
// не, это очень херовая масть, начнём с верной масти
tmp = hand->suitStart[gPassOutSuit];
if (tmp == crdNo) abort(); // а такого не бывает
if (tmp < crdNo) break; // ну нет у нас такой, и уже всё, что было, проверили
// скипаем и повторяем выборы
crdNo = tmp;
continue;
}
goto doMove;
}
// check for valid move
// выход в правильную масть?
if (crdSuit == xDeskSuits[0]) goto doMove;
// не, не та масть; ну-ка, чо у нас на руках ваще?
// нужная масть у нас есть?
if (hand->suitCount[xDeskSuits[0]]) {
// таки есть, потому это очень хуёвый вариант; ходим сразу с нужной масти
tmp = hand->suitStart[xDeskSuits[0]];
if (tmp < crdNo) break; // всё, нечего больше искать
if (tmp > crdNo) {
// скипаем
crdNo = tmp;
continue;
}
// вот этой и ходим
goto doMove;
}
// не, нужной масти нет
// а козырь есть?
if (gTrumpSuit <= 3) {
// игра козырная, есть козыри?
if (hand->suitCount[gTrumpSuit]) {
// таки есть
tmp = hand->suitStart[gTrumpSuit];
if (tmp < crdNo) break; // всё, нечего больше искать
if (tmp > crdNo) {
// скипаем
crdNo = tmp;
continue;
}
// вот этой и ходим
goto doMove;
} else {
// не, и козырей нет, можно кидать чо попало
goto doMove;
}
} else {
// игра бескозырная, тут любая карта пойдёт, хули
goto doMove;
}
doMove:
/*
movesChecked++;
if (firstm < 0) firstm = crdNo;
*/
// проскипаем последовательность из плавно убывающих карт одной масти
// очевидно, что при таком раскладе похуй, какой из них ходить
int scnt = hand->suitCount[crdSuit];
if (scnt > 1) {
// в этой масти есть ещё карты
// проверим, есть ли у кого ещё эта масть
if (xHands[0].suitCount[crdSuit]+xHands[1].suitCount[crdSuit]+xHands[2].suitCount[crdSuit] <= scnt) {
// единственный гордый владелец этой масти; пробуем только одну её карту
int tsuit = crdSuit+1;
while (tsuit <= 3 && hand->suitCount[tsuit] == 0) tsuit++;
crdNext = tsuit>3 ? 11 : hand->suitStart[tsuit];
} else {
// такая масть есть ещё у кого-то
int tface = crdFace+1;
while (crdNext <= 10 && hand->suits[crdNext] == crdSuit && hand->faces[crdNext] == tface) {
crdNext++;
tface++;
}
}
}
// кидаем карту на стол
xDeskSuits[turn] = crdSuit;
xDeskFaces[turn] = crdFace;
// убираем карту из руки
hand->suitCount[crdSuit]--;
if (crdNo == hand->suitStart[crdSuit]) hand->suitStart[crdSuit]++;
hand->faces[crdNo] = 0;
//lastMoveF = crdFace; lastMoveS = crdSuit;
int y, z, x;
if (turn == 2) {
// the turn is done, count tricks
//who = whoTakes(pdesk, gTrumpSuit);
// а кто, собственно, забрал?
if (gTrumpSuit <= 3) {
// trump game
if (xDeskSuits[0] == gTrumpSuit) {
// нулевой козырнул
who = 0; tmp = xDeskFaces[0];
if (xDeskSuits[1] == xDeskSuits[0] && xDeskFaces[1] > tmp) { tmp = xDeskFaces[1]; who = 1; }
if (xDeskSuits[2] == xDeskSuits[0] && xDeskFaces[2] > tmp) who = 2;
} else if (xDeskSuits[1] == gTrumpSuit) {
// первый козырнул
who = 1; tmp = xDeskFaces[0];
if (xDeskSuits[2] == xDeskSuits[1] && xDeskFaces[2] > tmp) who = 2;
} else if (xDeskSuits[2] == gTrumpSuit) {
// второй козырнул
who = 2;
} else {
// никто не козырял
who = 0; tmp = xDeskFaces[0];
if (xDeskSuits[1] == xDeskSuits[0] && xDeskFaces[1] > tmp) { tmp = xDeskFaces[1]; who = 1; }
if (xDeskSuits[2] == xDeskSuits[0] && xDeskFaces[2] > tmp) who = 2;
}
} else {
// notrump game
who = 0; tmp = xDeskFaces[0];
if (xDeskSuits[1] == xDeskSuits[0] && xDeskFaces[1] > tmp) { tmp = xDeskFaces[1]; who = 1; }
if (xDeskSuits[2] == xDeskSuits[0] && xDeskFaces[2] > tmp) who = 2;
}
who = (who+player+1)%3;
xHands[who].tricks++; // прибавили взятку
#ifdef ABDEBUG
printf("==%i takes; cards left: %i; turn: %i\n", who, xCardsLeft, turn);
printStatus(turn, player, 1);
#endif
if (xCardsLeft < 0) abort();
if (!xCardsLeft) {
// всё, отбомбились, даёшь коэффициенты
gIterations++;
if (gIterations%1000000 == 0) {
if (stTime.elapsed() >= 5000) {
stTime.start();
//cTime = getTimeMs();
//fprintf(stderr, "\r%i (%i seconds)\x1b[K", gIterations, (int)((cTime-xStTime)/1000));
fprintf(stderr, "\r%i\x1b[K", gIterations);
}
}
/*
y = xHands[newPlayer].tricks;
z = xHands[(newPlayer+1)%3].tricks;
x = xHands[(newPlayer+2)%3].tricks;
*/
x = xHands[player].tricks;
y = xHands[newPlayer].tricks;
z = xHands[(player+2)%3].tricks;
if (gPassOut) {
x = 10-x;
y = 10-y;
z = 10-z;
}
#ifdef ADVANCED_RES
if (player == gWhoPlays) {
// я играю; выиграл ли?
if (x < gGameBid) {
// нет, обезлаплен
x = -gGameBid-1; /*y = z = 666;*/
} else {
// да, взял своё
x = 20+gGameBid;
/*
switch (gGameBid) {
case 6:
if (y < 2) y = -666+y; // bad
if (z < 2) z = -666+z; // bad
break;
case 7: case 8: case 9:
if (y < 1) y = -666+y; // bad
if (z < 1) z = -666+z; // bad
break;
}
*/
}
} else {
// я вистую; получилось ли?
if (xHands[gWhoPlays].tricks < gGameBid) {
// по любому засадили чувачка
//x = 666-(gGameBid-xHands[gWhoPlays].tricks); // на сколько
// чувак в жопе
if (gWhoPlays == newPlayer) {
//y = -xHands[gWhoPlays].tricks-1;
//z = 666;
} else {
//z = -xHands[gWhoPlays].tricks-1;
//y = 666;
}
} else {
// нет, чувак, увы, взял своё; а я?
/*
switch (gGameBid) {
case 6:
if (x < 2) x = -15-x; else x = 15+x;
break;
case 7: case 8: case 9:
if (x < 1) x = -15-x; else x = 15+x;
break;
}
if (gWhoPlays == newPlayer) {
y = 666;
switch (gGameBid) {
case 6:
if (z < 2) z = -15-z; else z = 15+z;
break;
case 7: case 8: case 9:
if (z < 1) z = -15-z; else z = 15+z;
break;
}
} else {
z = 666;
switch (gGameBid) {
case 6:
if (y < 2) y = -15-y; else y = 15+y;
break;
case 7: case 8: case 9:
if (y < 1) y = -15-y; else y = 15+y;
break;
}
}
*/
}
}
#endif
//printStatus(2, player, 0);
} else {
// рекурсивно проверяем дальше
//abcPrune(newTurn, newPlayer, -c, -a, b, &y, &z, &x, NULL);
if (who == player) {
// я же и забрал, снова здорово
abcPrune(0, player, a, b, c, &x, &y, &z, NULL);
} else if (who == newPlayer) {
// следующий забрал; красота и благолепие
abcPrune(0, newPlayer, -c, -a, b, &y, &z, &x, NULL);
} else {
// предыдущий забрал; вот такие вот параметры вышли; путём трэйсинга, да
abcPrune(0, who, -b, c, -a, &z, &x, &y, NULL);
}
}
// брали взятку? восстановим статус кво
xHands[who].tricks--;
} else {
// рекурсивно проверяем дальше
abcPrune(newTurn, newPlayer, -c, -a, b, &y, &z, &x, NULL);
}
// восстановим стол
xDeskFaces[0] = sDeskFaces[0]; xDeskFaces[1] = sDeskFaces[1]; xDeskFaces[2] = sDeskFaces[2];
xDeskSuits[0] = sDeskSuits[0]; xDeskSuits[1] = sDeskSuits[1]; xDeskSuits[2] = sDeskSuits[2];
// вернём в руку карту
hand->suitCount[crdSuit]++;
hand->faces[crdNo] = crdFace;
if (crdNo+1 == hand->suitStart[crdSuit]) hand->suitStart[crdSuit]--;
// проверим, чо нашли
if (bestm >= 0 && x == bestx) {
// we've found an equivalent move
//if (bestm < 0) abort();
n++;
if (y < worsty) worsty = y;
if (z < worstz) worstz = z;
//if (myrand()%n == n-1) bestm = crdNo;
// hands are sorted, so take the smallest possible card
if (bestm < 0 || crdFace < hand->faces[bestm]) bestm = crdNo;
} else if (x > bestx) {
// we've found a better move
n = 1;
bestm = crdNo;
bestx = x; worsty = y; worstz = z;
if (x > b || x > c) break; // всё, дальше искать не надо, всё равно мы крутые; goto done;
if (x > a) a = x;
}
// берём следующую карту
crdNo = crdNext;
}
xDeskFaces[0] = sDeskFaces[0]; xDeskFaces[1] = sDeskFaces[1]; xDeskFaces[2] = sDeskFaces[2];
xDeskSuits[0] = sDeskSuits[0]; xDeskSuits[1] = sDeskSuits[1]; xDeskSuits[2] = sDeskSuits[2];
if (turn == 2) {
xCardsLeft++;
}
*ra = bestx; *rb = worsty; *rc = worstz;
if (rm) *rm = bestm;
/*
if (rm) *rm = bestm>=0?bestm:firstm;
if (bestm < 0) {
fprintf(stderr, "first: %i (%i)\n", firstm, movesChecked);
}
*/
//lastMoveF = lmF; lastMoveS = lmS;
}
//static card_t hands[3][10];
static const char *cFaceS[8] = {" 7"," 8"," 9","10"," J"," Q"," K"," A"};
static const char *cSuitS[4] = {"s","c","d","h"};
static void printHand (tHand *hand) {
int z;
for (z = 0; z < 10; z++) {
if (hand->faces[z]) {
printf(" %s%s(%2i)", cFaceS[hand->faces[z]-7], cSuitS[hand->suits[z]], CARD(hand->faces[z], hand->suits[z]));
} else {
printf(" ...");
}
}
printf(" 0:(%i,%i); 1:(%i,%i); 2:(%i,%i); 3:(%i,%i)",
hand->suitCount[0], hand->suitStart[0],
hand->suitCount[1], hand->suitStart[1],
hand->suitCount[2], hand->suitStart[2],
hand->suitCount[3], hand->suitStart[3]);
printf("\n");
}
static void printDesk (int cnt) {
printf("desk:");
for (int z = 0; z < cnt; z++) {
printf(" %s%s(%2i)", cFaceS[xDeskFaces[z]-7], cSuitS[xDeskSuits[z]], CARD(xDeskFaces[z], xDeskSuits[z]));
}
printf("\n");
}
/*
* aLeftPlayer: next in turn
* aRightPlayer: prev in turn
* 0, 1th
* 1th, 2nd
*/
Card *CheatPlayer::moveSelectCard (Card *lMove, Card *rMove, Player *aLeftPlayer, Player *aRightPlayer, bool isPassOut) {
printf ("CheatPlayer (%d) moves\n", mPlayerNo);
card_t hands[3][10];
card_t desk[3];
int crdLeft = 0;
int trumpSuit = 0;
Player *movePlrObj = 0, *plst[3];
//again:
plst[0] = plst[1] = plst[2] = 0;
plst[mPlayerNo-1] = this;
plst[aLeftPlayer->number()-1] = aLeftPlayer;
plst[aRightPlayer->number()-1] = aRightPlayer;
// build hands
for (int c = 0; c < 3; c++) {
if (!plst[c]) abort();
CardList *clst = &(plst[c]->mCards);
//for (int f = 0; f < 10; f++) hds[c][f] = hands[c][f] = 0;
int pos = 0;
for (int f = 0; f < clst->size(); f++) {
Card *ct = clst->at(f);
if (!ct) continue;
hands[c][pos++] = CARD(ct->face(), ct->suit()-1);
if (pos > crdLeft) crdLeft = pos;
}
for (int f = pos; f < 10; f++) hands[c][f] = 0;
xsortCards(hands[c], pos);
}
if (!lMove && !rMove && crdLeft == 10) {
return AiPlayer::moveSelectCard(lMove, rMove, aLeftPlayer, aRightPlayer, isPassOut);
}
// find game
eGameBid bid;
if (mMyGame == gtPass || mMyGame == whist) {
bid = aLeftPlayer->myGame();
if (bid == gtPass || bid == whist) {
bid = aRightPlayer->myGame();
movePlrObj = aRightPlayer;
} else movePlrObj = aLeftPlayer;
} else {
bid = mMyGame;
movePlrObj = this;
}
gPassOut = (bid == g86 || bid == g86catch || bid == raspass);
trumpSuit = bid%10-1;//(bid-(bid/10)*10)-1;
/*
if (bid == g86catch || bid == g86 || bid == raspass) {
return Player::moveSelectCard(lMove, rMove, aLeftPlayer, aRightPlayer);
}
*/
if (bid == g86catch || bid == g86 || bid == raspass) {
trumpSuit = 4;
}
if (trumpSuit < 0) trumpSuit = 4;
fprintf(stderr, "po:%s; lm:%s, rm:%s\n", isPassOut?"y":"n", lMove?"y":"n", rMove?"y":"n");
if (isPassOut && rMove && !lMove) {
// это распасы, первый или второй круг, первый ход
gPassOutSuit = rMove->suit()-1;
fprintf(stderr, "pass-out: %i\n", gPassOutSuit);
rMove = 0;
} else gPassOutSuit = -1;
// build desk
int turn = 0;
if (lMove) {
desk[turn++] = CARD(lMove->face(), lMove->suit()-1);
if (rMove) desk[turn++] = CARD(rMove->face(), rMove->suit()-1);
} else if (rMove) {
desk[turn++] = CARD(rMove->face(), rMove->suit()-1);
}
// build hands
for (int f = 0; f < 3; f++) {
xHands[f].suitCount[0] = xHands[f].suitCount[1] = xHands[f].suitCount[2] = xHands[f].suitCount[3] = 0;
xHands[f].suitStart[0] = xHands[f].suitStart[1] = xHands[f].suitStart[2] = xHands[f].suitStart[3] = 11;
xHands[f].tricks = plst[f]->tricksTaken();
int st;
for (int z = 0; z < 10; z++) {
if (hands[f][z]) {
xHands[f].faces[z] = FACE(hands[f][z]);
st = xHands[f].suits[z] = SUIT(hands[f][z]);
if (xHands[f].suitCount[st]++ == 0) xHands[f].suitStart[st] = z;
} else xHands[f].faces[z] = 0;
}
}
// build desk
for (int f = 0; f < turn; f++) {
xDeskFaces[f] = FACE(desk[f]);
xDeskSuits[f] = SUIT(desk[f]);
}
int a, b, c, move;
int me = this->number()-1;
xCardsLeft = crdLeft;
gTrumpSuit = trumpSuit;
gIterations = 0;
printf("%shand 0:", this->number()==0?"*":" ");
printHand(&(xHands[0]));
printf("%shand 1:", this->number()==1?"*":" ");
printHand(&(xHands[1]));
printf("%shand 2:", this->number()==2?"*":" ");
printHand(&(xHands[2]));
printDesk(turn);
// оптимизации
/*
if (turn > 0) {
// можем вообще взять?
if (hands[me].suitCount(
}
*/
stTime = QTime::currentTime();
stTime.start();
abcPrune(turn, me, -666, 666, 666, &a, &b, &c, &move);
qDebug() <<
"face:" << FACE(hands[me][move]) <<
"suit:" << SUIT(hands[me][move])+1 <<
"move:" << move <<
"turn:" << turn <<
"moves:" << crdLeft <<
"trump:" << trumpSuit <<
"iters:" << gIterations <<
"";
/*
for (int h = 0; h < 3; h++) {
fprintf(stderr, (h == me)?"*":" ");
fprintf(stderr, "hand %i:", h);
for (int f = 0; f < 10; f++) {
if (hands[h][f]) {
fprintf(stderr, " %2i.%i(%3i)", FACE(hands[h][f]), SUIT(hands[h][f]), hands[h][f]);
} else {
fprintf(stderr, " %2i.%i(%3i)", 0, 0, hands[h][f]);
}
}
fprintf(stderr, "\n");
}
fprintf(stderr, "desk:");
for (int f = 0; f < turn; f++) {
fprintf(stderr, " %2i.%i(%3i)", FACE(desk[f]), SUIT(desk[f]), desk[f]);
}
fprintf(stderr, "\n");
*/
if (move < 0) {
fprintf(stderr, "fuck!\n");
//goto again;
abort();
}
Card *moveCard = newCard(FACE(hands[me][move]), SUIT(hands[me][move])+1);
qDebug() << "move:" << moveCard->toString();
mCards.remove(moveCard);
mCardsOut.insert(moveCard);
return moveCard;
}
///////////////////////////////////////////////////////////////////////////////
CheatPlayer::CheatPlayer (int aMyNumber, DeskView *aDeskView) : AiPlayer(aMyNumber, aDeskView) {
mInvisibleHand = false;
}
/*
CheatPlayer &CheatPlayer::operator = (const Player &pl) {
Player::clone(&pl);
mInvisibleHand = false;
return *this;
}
CheatPlayer &CheatPlayer::operator = (const CheatPlayer &pl) {
Player::clone(&pl);
if (allowDebugLog) mInvisibleHand = false;
return *this;
}
*/
openpref-0.1.3/src/logic/logic.pri 0000755 0001750 0001750 00000000355 11265177055 016453 0 ustar kostya kostya DEPENDPATH += $$PWD
INCLUDEPATH += $$PWD
HEADERS += \
$$PWD/player.h \
$$PWD/aiplayer.h \
$$PWD/human.h \
$$PWD/aialphabeta.h
SOURCES += \
$$PWD/player.cpp \
$$PWD/human.cpp \
$$PWD/aiplayer.cpp \
$$PWD/aialphabeta.cpp
openpref-0.1.3/src/logic/logic.cmake 0000644 0001750 0001750 00000000413 11265177055 016731 0 ustar kostya kostya project(openpref)
SET ( HEADERS ${HEADERS}
src/logic/player.h
src/logic/aiplayer.h
src/logic/human.h
src/logic/aialphabeta.h
)
SET ( SOURCES ${SOURCES}
src/logic/player.cpp
src/logic/human.cpp
src/logic/aiplayer.cpp
src/logic/aialphabeta.cpp
) openpref-0.1.3/src/logic/human.cpp 0000755 0001750 0001750 00000016045 11265177055 016461 0 ustar kostya kostya /*
* OpenPref - cross-platform Preferans game
*
* Copyright (C) 2000-2009 OpenPref Developers
* (see file AUTHORS for more details)
* Contact: annulen@users.sourceforge.net
*
* OpenPref is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (see file COPYING); if not, see
* http://www.gnu.org/licenses
*/
#include
#include
#include
#include "prfconst.h"
#include "formbid.h"
#include "kpref.h"
#include "deskview.h"
#include "player.h"
#include "card.h"
#include "cardlist.h"
#include "ncounter.h"
#include "plscore.h"
#include "human.h"
HumanPlayer::HumanPlayer (int aMyNumber, DeskView *aDeskView) : Player(aMyNumber, aDeskView) {
internalInit();
}
HumanPlayer &HumanPlayer::operator = (const Player &pl) {
Player::clone(&pl);
return *this;
}
HumanPlayer &HumanPlayer::operator = (const HumanPlayer &pl) {
Player::clone(&pl);
return *this;
}
void HumanPlayer::clear () {
Player::clear();
mInvisibleHand = false;
}
//
eGameBid HumanPlayer::dropForMisere () {
mClickX = mClickY = 0; mWaitingForClick = true;
moveSelectCard(0, 0, 0, 0);
//mDeskView->mySleep(1);
moveSelectCard(0, 0, 0, 0);
mWaitingForClick = false;
return g86;
}
//
eGameBid HumanPlayer::dropForGame () {
//mWaitingForClick = 1;
//mClickX = mClickY = 0;
eGameBid tmpGamesType;
moveSelectCard(0, 0, 0, 0);
//!.!mDeskView->mySleep(1);
moveSelectCard(0, 0, 0, 0);
formBid->enableAll();
formBid->disableItem(whist);
//formBid->disableItem(halfwhist);
formBid->bhalfvist->setEnabled(false);
formBid->disableItem(gtPass);
if (mMyGame != g86) formBid->disableItem(g86);
formBid->disableLessThan(mMyGame);
formBid->showbullet->setEnabled(true);
if (optWithoutThree)
formBid->bwithoutthree->setEnabled(true);
do {
tmpGamesType = mDeskView->selectBid(zerogame, zerogame);
if (tmpGamesType == 0) {
//
clearCardArea();
returnDrop();
moveSelectCard(0, 0, 0, 0);
//mDeskView->mySleep(1);
moveSelectCard(0, 0, 0, 0);
} else if (tmpGamesType == 1) {
//
kpref->slotShowScore();
}
} while (tmpGamesType <= 1);
if ( tmpGamesType != withoutThree)
mMyGame = tmpGamesType;
formBid->enableAll();
mWaitingForClick = false;
return tmpGamesType;
}
//
eGameBid HumanPlayer::moveBidding (eGameBid lMove, eGameBid rMove) {
eGameBid tmpGamesType;
mClickX = mClickY = 0; mWaitingForClick = true;
//fprintf(stderr, "select bid\n");
formBid->enableAll();
/*if (optAggPass && optPassCount > 0) {
if (lMove == undefined) lMove = g71;
if (rMove == undefined) rMove = g71;
}*/
if (optAggPass && optPassCount > 0)
formBid->disableLessThan(g71);
if (qMax(lMove, rMove) != gtPass)
{
// If HumanPlayer started bid, he can stay
//mIStart = (lMove == undefined && rMove == undefined);
if (mIStart)
formBid->disableLessThan(qMax(lMove, rMove));
// otherwise he must increase
else
formBid->disableLessThan(qMax((eGameBid)succBid(lMove), (eGameBid)succBid(rMove)));
}
if (mMyGame != undefined)
formBid->disableItem(g86);
formBid->enableItem(gtPass);
formBid->disableItem(whist);
//formBid->disableItem(halfwhist);
formBid->bhalfvist->setEnabled(false);
formBid->showbullet->setEnabled(true);
formBid->bwithoutthree->setEnabled(false);
do {
tmpGamesType = mDeskView->selectBid(lMove, rMove);
if (tmpGamesType == 0) {
// ( )
clearCardArea();
returnDrop();
moveSelectCard(0, 0, 0, 0);
//mDeskView->mySleep(1);
moveSelectCard(0, 0, 0, 0);
} else if (tmpGamesType == 1) {
// show pool
kpref->mDesktop->mShowPool = true;
kpref->slotShowScore();
}
} while (tmpGamesType <= 1);
mMyGame = tmpGamesType;
mWaitingForClick = false;
formBid->enableAll();
return mMyGame;
}
//move
Card *HumanPlayer::moveSelectCard (Card *lMove, Card *rMove, Player *aLeftPlayer, Player *aRightPlayer, bool isPassOut) {
Q_UNUSED(aLeftPlayer)
Q_UNUSED(aRightPlayer)
Q_UNUSED(isPassOut)
printf ("HumanPlayer (%d) moves\n", mPlayerNo);
Card *res = 0;
mClickX = mClickY = 0; mWaitingForClick = true;
kpref->HintMove();
draw();
while (!res) {
if (mDeskView) mDeskView->mySleep(-2);
int cNo = cardAt(mClickX, mClickY, !invisibleHand());
if (cNo == -1) {
mClickX = mClickY = 0;
//draw();
continue;
}
//qDebug() << "selected:" << cNo << "mClickX:" << mClickX << "mClickY:" << mClickY;
Card *Validator;
int koz = trumpSuit();
Validator = res = mCards.at(cNo);
if (lMove || rMove) {
Validator = lMove ? lMove : rMove;
}
if (!Validator || !res) continue;
// check if move accords with rules
if (!((Validator->suit() == res->suit()) ||
(!mCards.minInSuit(Validator->suit()) && (res->suit() == koz || ((!mCards.minInSuit(koz)))))
)) {
kpref->MoveImpossible();
res = 0;
}
}
clearCardArea();
mPrevHiCardIdx = -1;
mCards.remove(res);
mCardsOut.insert(res);
mClickX = mClickY = 0; mWaitingForClick = false;
kpref->HintBar->clearMessage();
draw();
return res;
}
eGameBid HumanPlayer::moveFinalBid (eGameBid MaxGame, int HaveAVist, int nGamerPass) {
Q_UNUSED(HaveAVist)
//Q_UNUSED(nGamerVist)
//fprintf(stderr, "whist/pass\n");
if (MaxGame == g86) {
mMyGame = g86catch;
} else if (!opt10Whist && MaxGame>=101 && MaxGame<=105) {
mMyGame = whist;
} else {
// Stalingrad?
formBid->disableAll();
if (optStalingrad && MaxGame == g61) formBid->disableItem(gtPass);
else formBid->enableItem(gtPass);
//formBid->enableItem(gtPass);
formBid->enableItem(whist);
if (nGamerPass == 1)
formBid->bhalfvist->setEnabled(true);
mMyGame = mDeskView->selectBid(zerogame, zerogame);
formBid->enableAll();
}
return mMyGame;
}
void HumanPlayer::hilightCard (int lx, int ly) {
//qDebug() << "lx:" << lx << "ly:" << ly;
if (!mWaitingForClick) {
// not in "card selection" mode
if (mPrevHiCardIdx == -1) return; // nothing selected --> nothing to redraw
mPrevHiCardIdx = -1;
} else {
int cNo = cardAt(lx, ly, !invisibleHand());
if (cNo == mPrevHiCardIdx) return; // same selected --> nothing to redraw
//qDebug() << "mPrevHiCardIdx:" << mPrevHiCardIdx << "cNo:" << cNo;
mPrevHiCardIdx = cNo;
}
draw();
kpref->HintBar->clearMessage();
}
bool HumanPlayer::chooseClosedWhist () {
return kpref->WhistType();
}
openpref-0.1.3/src/logic/aiplayer.h 0000755 0001750 0001750 00000010201 11265177055 016610 0 ustar kostya kostya /*
* OpenPref - cross-platform Preferans game
*
* Copyright (C) 2000-2009 OpenPref Developers
* (see file AUTHORS for more details)
* Contact: annulen@users.sourceforge.net
*
* OpenPref is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (see file COPYING); if not, see
* http://www.gnu.org/licenses
*/
#ifndef AIPLAYER_H
#define AIPLAYER_H
#include "prfconst.h"
#include "card.h"
#include "cardlist.h"
#include "ncounter.h"
#include "player.h"
#include "plscore.h"
#include "deskview.h"
class AiPlayer : public Player {
public:
AiPlayer (int aMyNumber, DeskView *aDeskView=0);
public:
virtual Card *moveSelectCard (Card *lMove, Card *rMove, Player *aLeftPlayer, Player *aRightPlayer, bool isPassOut); //
virtual eGameBid moveBidding (eGameBid lMove, eGameBid rMove); //
virtual eGameBid moveFinalBid (eGameBid MaxGame, int HaveAWhist, int nGamerWhist); // -
virtual eGameBid dropForGame ();
virtual eGameBid dropForMisere ();
virtual bool chooseClosedWhist ();
virtual void clear ();
protected:
bool checkForMisere ();
eGameBid moveCalcDrop (); //
tSuitProbs countGameTricks (eSuit, int a23);
tSuitProbs countTricks (eSuit, CardList &, int a23);
tSuitProbs countPassTricks (eSuit, CardList &);
//
tSuitProbs calcProbsForMax (CardList &my, CardList &enemy); // 1
tSuitProbs calcProbsForMaxH23 (CardList &my, CardList &enemy); // 2 3
tSuitProbs calcProbsForMin (CardList &my, CardList &enemy); //
void recalcTables (CardList &aMaxCardList, int a23); // tSuitProbs mSuitProb[5];
void recalcPassOutTables (CardList &aMaxCardList, int a23); //
void loadLists (Player *aLeftPlayer, Player *aRightPlayer, CardList &aMaxCardList); //
Card *GetMaxCardPere ();
Card *GetMaxCardWithOutPere ();
Card *GetMinCardWithOutVz ();
Card *Miser1 (Player *aLeftPlayer, Player *aRightPlayer);
Card *Miser2 (Card *aRightCard, Player *aLeftPlayer, Player *aRightPlayer);
Card *Miser3 (Card *aLeftCard, Card *aRightCard, Player *aLeftPlayer, Player *aRightPlayer);
Card *MyGame1 (Player *aLeftPlayer, Player *aRightPlayer); // 1 -
Card *MyGame2 (Card *aRightCard, Player *aLeftPlayer, Player *aRightPlayer); // 2 -
Card *MyGame3 (Card *aLeftCard, Card *aRightCard, Player *aLeftPlayer, Player *aRightPlayer); // 3 -
Card *MyWhist1 (Player *aLeftPlayer, Player *aRightPlayer); // 1 -
Card *MyWhist2 (Card *aRightCard, Player *aLeftPlayer, Player *aRightPlayer); // 2 -
Card *MyWhist3 (Card *aLeftCard, Card *aRightCard, Player *aLeftPlayer, Player *aRightPlayer); // 3 -
// !!!
Card *MyPass1 (Card *, Player *aLeftPlayer, Player *aRightPlayer);
Card *MyPass2 (Card *aRightCard, Player *aLeftPlayer, Player *aRightPlayer); // 2 -
Card *MyPass3 (Card *aLeftCard, Card *aRightCard, Player *aLeftPlayer, Player *aRightPlayer); // 3 -
Card *MiserCatch1 (Player *aLeftPlayer, Player *aRightPlayer);
Card *MiserCatch2 (Card *aRightCard, Player *aLeftPlayer, Player *aRightPlayer);
Card *MiserCatch3 (Card *aLeftCard, Card *aRightCard, Player *aLeftPlayer, Player *aRightPlayer);
protected:
tSuitProbs mSuitProb[5];
};
#endif
openpref-0.1.3/src/logic/aialphabeta.h 0000755 0001750 0001750 00000002557 11265177055 017254 0 ustar kostya kostya /*
* OpenPref - cross-platform Preferans game
*
* Copyright (C) 2000-2009 OpenPref Developers
* (see file AUTHORS for more details)
* Contact: annulen@users.sourceforge.net
*
* OpenPref is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (see file COPYING); if not, see
* http://www.gnu.org/licenses
*/
#ifndef AIALPHABETA_H
#define AIALPHABETA_H
#include "aiplayer.h"
#include "prfconst.h"
#include "card.h"
#include "cardlist.h"
#include "ncounter.h"
#include "plscore.h"
#include "deskview.h"
#include "player.h"
class CheatPlayer : public AiPlayer {
public:
CheatPlayer (int aMyNumber, DeskView *aDeskView=0);
Card *moveSelectCard (Card *lMove, Card *rMove, Player *aLeftPlayer, Player *aRightPlayer, bool isPassOut); //
};
#endif
openpref-0.1.3/src/logic/player.h 0000755 0001750 0001750 00000007224 11265177055 016311 0 ustar kostya kostya /*
* OpenPref - cross-platform Preferans game
*
* Copyright (C) 2000-2009 OpenPref Developers
* (see file AUTHORS for more details)
* Contact: annulen@users.sourceforge.net
*
* OpenPref is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (see file COPYING); if not, see
* http://www.gnu.org/licenses
*/
#ifndef PLAYER_H
#define PLAYER_H
#include "prfconst.h"
#include "card.h"
#include "cardlist.h"
#include "ncounter.h"
#include "plscore.h"
#include "deskview.h"
class Player {
public:
Player (int aMyNumber, DeskView *aDeskView=0);
Player (const Player &pl);
virtual ~Player ();
Player &operator = (const Player &pl);
virtual void clear ();
virtual bool invisibleHand () const;
virtual void setInvisibleHand (bool invis);
virtual void setCurrentStart (bool start);
virtual void sortCards ();
virtual void dealCard (Card *aCard); // get dealed card
virtual Card *moveSelectCard (Card *lMove, Card *rMove, Player *aLeftPlayer, Player *aRightPlayer, bool isPassOut) = 0; //move
virtual eGameBid moveBidding (eGameBid lMove, eGameBid rMove) = 0; //
virtual eGameBid moveFinalBid (eGameBid MaxGame, int HaveAWhist, int nGamerWhist) = 0; // --
virtual eGameBid dropForGame () = 0; //
virtual eGameBid dropForMisere () = 0; //
virtual void returnDrop (); //
virtual bool chooseClosedWhist () = 0;
virtual void getLeftTop (int *left, int *top);
virtual void draw ();
virtual void hilightCard (int lx, int ly); // ( , )
inline void setMessage (const QString &msg) { mMessage = msg; }
inline const QString &message () const { return mMessage; }
inline int number () const { return mPlayerNo; }
inline eGameBid myGame () const { return mMyGame; }
inline void setMyGame (eGameBid game) { mMyGame = game; }
inline int tricksTaken () const { return mTricksTaken; }
virtual void gotTrick ();
virtual void gotPassPassTricks (int cnt);
protected:
virtual void internalInit ();
virtual void clone (const Player *pl);
virtual void drawAt (DeskView *aDeskView, int left, int top, int selNo=-1);
virtual void clearCardArea ();
// at least 28 ints (14 int pairs); return # of used ints; the last int is -1
// result: ofs, cardNo, ..., -1
virtual int buildHandXOfs (int *dest, int startX, bool opened);
virtual int cardAt (int lx, int ly, bool opened=true);
public:
DeskView *mDeskView;
ScoreBoard mScore;
CardList mCards; // my cards
CardList mLeft; // cards of left player (supposed or open)
CardList mRight; // cards of right player (supposed or open)
CardList mOut; // dropped cards (my or supposed)
CardList mCardsOut; //
// this part for miser catches
Card *mCardCarryThru;
int mClickX, mClickY;
bool mWaitingForClick;
protected:
QString mNick;
QString mMessage;
int mPlayerNo; // my number
bool mInvisibleHand;
eGameBid mMyGame;
int mTricksTaken;
int mPrevHiCardIdx;
bool mIStart;
};
#endif
openpref-0.1.3/src/logic/human.h 0000755 0001750 0001750 00000003546 11265177055 016130 0 ustar kostya kostya /*
* OpenPref - cross-platform Preferans game
*
* Copyright (C) 2000-2009 OpenPref Developers
* (see file AUTHORS for more details)
* Contact: annulen@users.sourceforge.net
*
* OpenPref is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (see file COPYING); if not, see
* http://www.gnu.org/licenses
*/
#ifndef HUMAN_H
#define HUMAN_H
#include "prfconst.h"
#include "card.h"
#include "cardlist.h"
#include "ncounter.h"
#include "plscore.h"
#include "deskview.h"
#include "player.h"
class HumanPlayer : public Player {
public:
HumanPlayer (int aMyNumber, DeskView *aDeskView=0);
HumanPlayer &operator = (const Player &pl);
HumanPlayer &operator = (const HumanPlayer &pl);
virtual void clear ();
virtual Card *moveSelectCard (Card *lMove, Card *rMove, Player *aLeftPlayer, Player *aRightPlayer, bool isPassOut=false); //
virtual eGameBid moveBidding (eGameBid lMove, eGameBid rMove); //
virtual eGameBid moveFinalBid (eGameBid MaxGame, int HaveAVist, int nGamerVist); // -
virtual eGameBid dropForGame (); //
virtual eGameBid dropForMisere ();
virtual bool chooseClosedWhist ();
virtual void hilightCard (int lx, int ly);
};
#endif
openpref-0.1.3/src/logic/player.cpp 0000755 0001750 0001750 00000014126 11265177055 016643 0 ustar kostya kostya /*
* OpenPref - cross-platform Preferans game
*
* Copyright (C) 2000-2009 OpenPref Developers
* (see file AUTHORS for more details)
* Contact: annulen@users.sourceforge.net
*
* OpenPref is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (see file COPYING); if not, see
* http://www.gnu.org/licenses
*/
#include
#include
#include
#include
#include "player.h"
Player::Player (int aMyNumber, DeskView *aDeskView) : mDeskView(aDeskView), mIStart(false), mPlayerNo(aMyNumber) {
internalInit();
}
Player::Player (const Player &pl) {
internalInit();
clone(&pl);
}
Player::~Player () {
clear();
}
inline void Player::internalInit () {
clear();
}
Player &Player::operator = (const Player &pl) {
clone(&pl);
return *this;
}
void Player::clone (const Player *pl) {
if (pl && pl != this) {
mDeskView = pl->mDeskView;
mCards = pl->mCards;
mLeft = pl->mLeft;
mRight = pl->mRight;
mOut = pl->mOut;
mCardsOut = pl->mCardsOut;
mCardCarryThru = pl->mCardCarryThru;
mNick = pl->mNick;
mMessage = pl->mMessage;
mPlayerNo = pl->mPlayerNo;
mInvisibleHand = pl->mInvisibleHand;
mMyGame = pl->mMyGame;
mTricksTaken = pl->mTricksTaken;
mPrevHiCardIdx = pl->mPrevHiCardIdx;
}
}
void Player::clear () {
mCards.clear();
mLeft.clear();
mRight.clear();
mOut.clear();
mCardsOut.clear();
mCardCarryThru = 0;
mMessage.clear();
mInvisibleHand = (mPlayerNo != 1);
mMyGame = undefined;
mTricksTaken = 0;
mWaitingForClick = false;
mPrevHiCardIdx = -1;
}
inline bool Player::invisibleHand () const {
return optDebugHands ? false : mInvisibleHand;
}
inline void Player::setInvisibleHand (bool invis) {
mInvisibleHand = invis;
}
inline void Player::setCurrentStart (bool start) {
mIStart = start;
}
inline void Player::sortCards () {
mCards.mySort();
}
inline void Player::dealCard (Card *aCard) {
mCards.insert(aCard);
}
void Player::returnDrop () {
if (mCardsOut.at(0)) mCards.insert(mCardsOut.at(0));
if (mCardsOut.at(1)) mCards.insert(mCardsOut.at(1));
mCardsOut.clear();
}
inline void Player::gotTrick () {
mTricksTaken++;
}
inline void Player::gotPassPassTricks (int cnt) {
mTricksTaken = cnt;
}
///////////////////////////////////////////////////////////////////////////////
// game graphics
///////////////////////////////////////////////////////////////////////////////
void Player::getLeftTop (int *left, int *top) {
*left = 0; *top = 0;
if (!mDeskView) return;
switch (mPlayerNo) {
case 1:
*left = (mDeskView->DesktopWidth-(mDeskView->DesktopWidth/2-2*mDeskView->xBorder))/2;
*top = mDeskView->DesktopHeight-(mDeskView->yBorder)-CARDHEIGHT;//mDeskView->CardHeight;//-10;
break;
case 2:
*left = mDeskView->xBorder;
*top = mDeskView->yBorder+20;
break;
case 3:
*left = mDeskView->DesktopWidth-mDeskView->xBorder;
*top = mDeskView->yBorder+20;
break;
default: ;
}
}
///////////////////////////////////////////////////////////////////////////////
// build array with cards offsets and indicies
// at least 28 ints (14 int pairs); return # of used ints; the last int is -1
// result: ofs, cardNo, ..., -1
int Player::buildHandXOfs (int *dest, int startX, bool opened) {
int cnt = 0, oldXX = startX, *oDest = dest;
Card *cur = 0, *prev = 0;
CardList lst(mCards);
lst.mySort();
if (mPlayerNo == 3) startX = 0;
// normal
startX -= opened ? SUIT_OFFSET : CLOSED_CARD_OFFSET ;
for (int f = 0; f < lst.size(); f++) {
Card *pp = lst.at(f);
if (!pp) continue;
prev = cur;
cur = pp;
if (opened) {
startX += (prev && prev->suit() != cur->suit()) ? NEW_SUIT_OFFSET : SUIT_OFFSET ;
} else startX += CLOSED_CARD_OFFSET;
*dest++ = startX;
int idx = mCards.indexOf(cur);
*dest++ = idx;
if (idx < 0) abort();
cnt++;
if (cnt > 12) abort();
}
*dest++ = -1;
*dest = -1;
if (mPlayerNo == 3 && cnt) {
// righttop
startX = oldXX-(oDest[(cnt-1)*2]+CARDWIDTH+4);
for (int f = 0; f < cnt; f++) oDest[f*2] += startX;
}
return cnt;
}
int Player::cardAt (int lx, int ly, bool opened) {
int res = -1, ofs[28];
int left, top;
getLeftTop(&left, &top);
buildHandXOfs(ofs, left, opened);
for (int f = 0; ofs[f] >= 0; f += 2) {
int x1 = ofs[f], y1 = top;//+mDeskView->yBorder;
int x2 = x1+CARDWIDTH, y2 = y1+CARDHEIGHT;
if (x1 < lx && lx < x2 && y1 < ly && ly < y2) res = ofs[f+1];
}
return res;
}
void Player::drawAt (DeskView *aDeskView, int left, int top, int selNo) {
int ofs[28];
DeskView *oDesk = mDeskView;
if (!aDeskView) return;
mDeskView = aDeskView;
int cnt = buildHandXOfs(ofs, left, !invisibleHand());
if (cnt) left = ofs[0];
for (int f = 0; ofs[f] >= 0; f += 2) {
int x = ofs[f], y = top;
Card *card = mCards.at(ofs[f+1]);
aDeskView->drawCard(card, x, y, !invisibleHand(), ofs[f+1]==selNo);
}
aDeskView->emitRepaint();
mDeskView = oDesk;
}
void Player::draw () {
int left, top;
if (!mDeskView) return;
getLeftTop(&left, &top);
drawAt(mDeskView, left, top, mPrevHiCardIdx);
}
void Player::clearCardArea () {
int left, top, ofs[28];
if (!mDeskView) return;
getLeftTop(&left, &top);
int cnt = buildHandXOfs(ofs, left, !invisibleHand());
if (!cnt) return;
for (int f = 0; ofs[f] >= 0; f += 2) {
int x = ofs[f], y = top;
mDeskView->ClearBox(x, y, CARDWIDTH, CARDHEIGHT);
}
}
void Player::hilightCard (int lx, int ly) {
Q_UNUSED(lx)
Q_UNUSED(ly)
mPrevHiCardIdx = -1;
}
openpref-0.1.3/src/score/ 0000755 0001750 0001750 00000000000 11265437521 014647 5 ustar kostya kostya openpref-0.1.3/src/score/plscore.cpp 0000755 0001750 0001750 00000016240 11265177055 017033 0 ustar kostya kostya /*
* OpenPref - cross-platform Preferans game
*
* Copyright (C) 2000-2009 OpenPref Developers
* (see file AUTHORS for more details)
* Contact: annulen@users.sourceforge.net
*
* OpenPref is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (see file COPYING); if not, see
* http://www.gnu.org/licenses
*/
#include "plscore.h"
#include "baser.h"
#include "prfconst.h"
static QString intList2Str (const QIntList &list, int maxItems) {
QString res;
int st = 1, len = list.size();
if (maxItems == 0) return QString();
if (maxItems > 0 && len > maxItems) st += (maxItems-len);
for (int f = st; f < list.size(); f++) {
//if (!res.isEmpty()) res += '.';
res += QString::number(list[f]);
res += '.';
}
return res;
}
///////////////////////////////////////////////////////////////////////////////
ScoreBoard::ScoreBoard () {
mPool << 0;
mMountain << 0;
mLeftWhists << 0;
mRightWhists << 0;
mWhists = 0;
}
ScoreBoard::~ScoreBoard () {
}
int ScoreBoard::poolAdd (int delta) {
int score = pool();
int ns = score+delta;
if (ns <= optMaxPool) {
mPool << ns;
return 0;
} else {
if (optMaxPool != score) mPool << optMaxPool;
return delta-(optMaxPool-score);
}
}
void ScoreBoard::mountainDown (int delta) {
if (delta == 0)
return;
int score = mountain()-delta;
if (score >= 0) {
mMountain << score;
} else {
score = (delta-mountain())*10/2;
if (mountain()) mMountain << 0;
mLeftWhists << leftWhists()+score;
mRightWhists << rightWhists()+score;
}
}
void ScoreBoard::mountainAmnesty (int delta) {
if (delta == 0)
return;
mMountain.last() -= delta;
if ((mMountain.last() == 0) || (mMountain.at(mMountain.size()-2) == mMountain.last()))
mMountain.removeLast();
}
void ScoreBoard::mountainUp (int delta) {
if (delta == 0)
return;
int score = mountain();
mMountain << score+delta;
}
void ScoreBoard::whistsAdd (int index, int myNumber, int delta) {
QIntList *dList;
int score;
dList = ((myNumber%3)+1 == index) ? &mLeftWhists : &mRightWhists;
int pnCurrent = dList->at(dList->size()-1);
score = pnCurrent+delta*10;
dList->append(score);
}
int ScoreBoard::recordScores (
eGameBid aGamerType,
eGameBid aMyType,
int nGamerVz, //
int nMyVz, //c
int nGamer,
int myNumber,
int nqVist //-
)
{
int nGamePrice = gamePoolPrice(aGamerType); //
int nGameCard = gameTricks(aGamerType); //
int nVistCard = gameWhists(aGamerType); // -
int score = 0, pnCurrent = 0;
QIntList *dList;
if (aMyType >= g61 && aMyType != g86) {
// - !
if (nGamerVz >= nGameCard) {
// !
return poolAdd(nGamePrice);
} else {
//
pnCurrent = mMountain[mMountain.size()-1];
score = nGamePrice*(nGameCard-nMyVz)+pnCurrent;
if (score) mMountain << score;
}
return 0;
}
//-------------------------------------------------------------------------
if (aMyType == g86) {
if (nMyVz) {
mountainUp(nGamePrice*nMyVz);
return 0;
}
return poolAdd(10);
}
//-------------------------------------------------------------------------
if (aMyType == raspass) {
pnCurrent = mMountain[mMountain.size()-1];
score = nGamePrice*(nMyVz)+pnCurrent;
if (nMyVz && score) {
mMountain << score;
return 0;
}
if (!nMyVz) return poolAdd(1);
}
dList = ((myNumber%3)+1 == nGamer) ? &mLeftWhists : &mRightWhists;
pnCurrent = dList->at(dList->size()-1);
//-------------------------------------------------------------------------
if (aMyType == gtPass && aGamerType != g86) {
if (!optWhistGreedy && nGameCard-nGamerVz > 0) {
// ()
score = nGamePrice*((nGameCard-nGamerVz)+nMyVz)+pnCurrent;
}
if (score) dList->append(score);
}
if (aMyType == halfwhist && aGamerType != g86) {
score = nGamePrice*nMyVz+pnCurrent;
if (score) dList->append(score);
}
//-------------------------------------------------------------------------
if (aMyType == whist && aGamerType != g86) {
if (nGameCard-nGamerVz > 0) {
// ()
if (nqVist == 2) {
// 2
// +
score = nGamePrice*((nGameCard-nGamerVz)+nMyVz)+pnCurrent;
} else {
// 1
// +
score = nGamePrice*((nGameCard-nGamerVz)+nMyVz)+pnCurrent;
}
} else {
// ϣ
if (nqVist == 2) {
score = nGamePrice*(nMyVz)+pnCurrent;
} else {
score = nGamePrice*(10-nGamerVz)+pnCurrent;
}
// !
if (nVistCard > 10-nGamerVz) {
if (nqVist == 2) {
// 2
double d = nVistCard;
d = (d/2-nMyVz)*nGamePrice;
mountainUp((int)d);
} else {
// 1
if (nVistCard-nMyVz > 0) mountainUp(nGamePrice*(nVistCard-(10-nGamerVz)));
}
}
}
if (score) dList->append(score);
}
return 0;
}
QString ScoreBoard::poolStr (int maxItems) const { return intList2Str(mPool, maxItems); }
QString ScoreBoard::mountainStr (int maxItems) const { return intList2Str(mMountain, maxItems); }
QString ScoreBoard::leftWhistsStr (int maxItems) const { return intList2Str(mLeftWhists, maxItems); }
QString ScoreBoard::rightWhistsStr (int maxItems) const { return intList2Str(mRightWhists, maxItems); }
static void serializeIntList (QByteArray &ba, const QIntList &lst) {
serializeInt(ba, lst.size());
for (int f = 0; f < lst.size(); f++) serializeInt(ba, lst[f]);
}
static bool unserializeIntList (QByteArray &ba, int *pos, QIntList &lst) {
int t;
lst.clear();
if (!unserializeInt(ba, pos, &t)) return false;
while (t-- > 0) {
int c;
if (!unserializeInt(ba, pos, &c)) return false;
lst << c;
}
return true;
}
void ScoreBoard::serialize (QByteArray &ba) {
serializeIntList(ba, mPool);
serializeIntList(ba, mMountain);
serializeIntList(ba, mLeftWhists);
serializeIntList(ba, mRightWhists);
serializeInt(ba, mWhists);
}
bool ScoreBoard::unserialize (QByteArray &ba, int *pos) {
if (!unserializeIntList(ba, pos, mPool)) return false;
if (!unserializeIntList(ba, pos, mMountain)) return false;
if (!unserializeIntList(ba, pos, mLeftWhists)) return false;
if (!unserializeIntList(ba, pos, mRightWhists)) return false;
if (!unserializeInt(ba, pos, &mWhists)) return false;
return true;
}
openpref-0.1.3/src/score/score.pri 0000755 0001750 0001750 00000000153 11265177055 016503 0 ustar kostya kostya DEPENDPATH += $$PWD
INCLUDEPATH += $$PWD
HEADERS += \
$$PWD/plscore.h
SOURCES += \
$$PWD/plscore.cpp
openpref-0.1.3/src/score/plscore.h 0000755 0001750 0001750 00000004327 11265177055 016503 0 ustar kostya kostya /*
* OpenPref - cross-platform Preferans game
*
* Copyright (C) 2000-2009 OpenPref Developers
* (see file AUTHORS for more details)
* Contact: annulen@users.sourceforge.net
*
* OpenPref is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (see file COPYING); if not, see
* http://www.gnu.org/licenses
*/
#ifndef PLSCORE_H
#define PLSCORE_H
#include
#include "prfconst.h"
class ScoreBoard {
public:
ScoreBoard ();
~ScoreBoard ();
int recordScores (eGameBid aGamerType, eGameBid aMyType, int nGamerVz, int nMyVz, int nGamer, int myNumber, int nqVist);
inline int pool () const { return mPool[mPool.size()-1]; }
inline int mountain () const { return mMountain[mMountain.size()-1]; }
inline int leftWhists () const { return mLeftWhists[mLeftWhists.size()-1]; }
inline int rightWhists () const { return mRightWhists[mRightWhists.size()-1]; }
int poolAdd (int delta);
void whistsAdd (int index, int myNumber, int delta);
void mountainDown (int delta);
void mountainAmnesty (int delta);
void mountainUp (int delta);
QString poolStr (int maxItems=-1) const;
QString mountainStr (int maxItems=-1) const;
QString leftWhistsStr (int maxItems=-1) const;
QString rightWhistsStr (int maxItems=-1) const;
inline QString whistsStr () const { return QString::number(mWhists); }
inline int whists () const { return mWhists; }
inline void setWhists (int w) { mWhists = w; }
void serialize (QByteArray &ba);
bool unserialize (QByteArray &ba, int *pos);
private:
QIntList mPool;
QIntList mMountain;
QIntList mLeftWhists;
QIntList mRightWhists;
int mWhists;
};
#endif
openpref-0.1.3/src/score/score.cmake 0000644 0001750 0001750 00000000167 11265177055 016773 0 ustar kostya kostya project(openpref)
SET ( HEADERS ${HEADERS}
src/score/plscore.h
)
SET ( SOURCES ${SOURCES}
src/score/plscore.cpp
) openpref-0.1.3/src/prfconst.cpp 0000755 0001750 0001750 00000010255 11265177055 016107 0 ustar kostya kostya /*
* OpenPref - cross-platform Preferans game
*
* Copyright (C) 2000-2009 OpenPref Developers
* (see file AUTHORS for more details)
* Contact: annulen@users.sourceforge.net
*
* OpenPref is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (see file COPYING); if not, see
* http://www.gnu.org/licenses
*/
#include
#include
#include
#include "prfconst.h"
#include "card.h"
bool optStalingrad = true;
bool opt10Whist = false;
bool optWhistGreedy = true;
int optMaxPool = 10;
eGameBid gCurrentGame;
#ifndef WIN32 // May be #ifdef POSIX?
QString optHumanName = getenv("USER");
#else
QString optHumanName = "";
#endif
QString optPlayerName1 = "Player 1";
bool optAlphaBeta1 = false;
QString optPlayerName2 = "Player 2";
bool optAlphaBeta2 = false;
bool optDebugHands = false;
bool optAggPass = false;
int optPassCount = 0;
bool optWithoutThree = true;
bool optDealAnim = true;
bool optTakeAnim = true;
bool optPrefClub = false;
int CARDWIDTH = 71;
int CARDHEIGHT = 96;
int trumpSuit (void) {
return gCurrentGame-(gCurrentGame/10)*10;
}
int succBid (eGameBid game) {
switch (game) {
case g86: return g91; // after misere
case g105: return g105; // last
case gtPass: return g61; // first
default: ;
}
if (game != undefined) {
int vz = game/10, mast = game-vz*10;
if (mast != 5) {
mast++;
} else {
mast = SuitSpades;
vz++;
}
return vz*10+mast;
}
return g61;
//return gtPass;
}
int gameTricks (eGameBid gType) {
if (gType >= g71 && gType <= 75) return 7;
if (gType >= g81 && gType <= 85) return 8;
if (gType == g86) return 0;
if (gType >= g91 && gType <= 95) return 9;
if (gType >= g101 && gType <= 105) return 10;
return 6;
}
int gameWhists (eGameBid gType) {
if (gType >= g71 && gType <= 75) return 2;
if (gType >= g81 && gType <= 85) return 1;
if (gType == g86) return 0;
if (gType >= g91 && gType <= 95) return 1;
if (gType >= g101 && gType <= 105) {
if (opt10Whist)
return 1;
else
return 0;
}
return 4;
}
int gameWhistsMin (eGameBid gType) {
if (gType >= g71 && gType <= 75) return 2;
if (gType >= g81 && gType <= 85) return 1;
if (gType == g86) return 0;
if (gType >= g91 && gType <= 95) return 1;
if (gType >= g101 && gType <= 105) return 0;
return 3;
}
int gamePoolPrice (eGameBid gType) {
if (gType >= g71 && gType <= 75) return 4;
if (gType >= g81 && gType <= 85) return 6;
if (gType == g86) return 10;
if (gType >= g91 && gType <= 95) return 8;
if (gType >= g101 && gType <= 105) return 10;
if (gType == raspass) return 1;
return 2;
}
eGameBid gameName2Type (const QString &s) {
if (s == "raspass") return raspass;
if (s == "whist") return whist;
if (s == "undefined") return undefined;
if (s == "pass") return gtPass;
if (s == "g61") return g61;
if (s == "g62") return g62;
if (s == "g63") return g63;
if (s == "g64") return g64;
if (s == "g65") return g65;
if (s == "g71") return g71;
if (s == "g72") return g72;
if (s == "g73") return g73;
if (s == "g74") return g74;
if (s == "g75") return g75;
if (s == "g81") return g81;
if (s == "g82") return g82;
if (s == "g83") return g83;
if (s == "g84") return g84;
if (s == "g85") return g85;
if (s == "g86") return g86;
if (s == "g91") return g91;
if (s == "g92") return g92;
if (s == "g93") return g93;
if (s == "g94") return g94;
if (s == "g95") return g95;
if (s == "g101") return g101;
if (s == "g102") return g102;
if (s == "g103") return g103;
if (s == "g104") return g104;
if (s == "g105") return g105;
return undefined;
}
openpref-0.1.3/src/kpref.h 0000755 0001750 0001750 00000005100 11265177055 015016 0 ustar kostya kostya /*
* OpenPref - cross-platform Preferans game
*
* Copyright (C) 2000-2009 OpenPref Developers
* (see file AUTHORS for more details)
* Contact: annulen@users.sourceforge.net
*
* OpenPref is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (see file COPYING); if not, see
* http://www.gnu.org/licenses
*/
#ifndef KPREF_H
#define KPREF_H
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#include
#include "desktop.h"
#include "deskview.h"
class Kpref : public QMainWindow {
Q_OBJECT
public:
Kpref();
~Kpref();
void init();
void initMenuBar();
//QPainter *p;
//pthread_t thread;
//int flthread;
void adjustDesk ();
// Messages
void MoveImpossible ();
void HintMove ();
bool WhistType ();
public slots:
void forceRepaint ();
void slotNewSingleGame ();
void slotShowScore ();
void slotFileOpen ();
void slotFileSave ();
void slotHelpAbout ();
void slotRules ();
void slotOptions ();
void slotDeckChanged ();
void slotQuit ();
//void slotAbortBid ();
private:
void saveOptions ();
void loadOptions ();
private:
QMenu *netgameMenu;
QMenu *fileMenu;
QMenu *viewMenu;
QMenu *helpMenu;
QAction *actNewGame;
QAction *actFileOpen;
QAction *actFileSave;
QAction *actQuit;
QAction *actOptions;
QAction *actAboutQt;
public:
PrefDesktop *mDesktop;
DeskView *mDeskView;
bool mWaitingMouseUp;
bool mInMouseMoveEvent;
bool mInPaintEvent;
QStatusBar * HintBar;
QLabel * Hint;
protected:
void paintEvent (QPaintEvent *);
void mousePressEvent (QMouseEvent *);
void mouseMoveEvent (QMouseEvent *);
void keyPressEvent (QKeyEvent *);
void closeEvent(QCloseEvent *event);
void resizeEvent(QResizeEvent *event);
};
extern Kpref *kpref;
#endif
openpref-0.1.3/src/main.cpp 0000755 0001750 0001750 00000004663 11265177055 015203 0 ustar kostya kostya /*
* OpenPref - cross-platform Preferans game
*
* Copyright (C) 2000-2009 OpenPref Developers
* (see file AUTHORS for more details)
* Contact: annulen@users.sourceforge.net
*
* OpenPref is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (see file COPYING); if not, see
* http://www.gnu.org/licenses
*/
#include
#include
#include
#include
#include
#include "main.h"
#include "debug.h"
#include "prfconst.h"
#include "kpref.h"
#include "formbid.h"
#ifndef LOCAL
#define i18n_PATH QCoreApplication::applicationDirPath()+"/../share/openpref/i18n"
#else
#define i18n_PATH "."
#endif
using namespace std;
int main (int argc, char *argv[]) {
QCoreApplication::setOrganizationName("OpenPref");
QCoreApplication::setOrganizationDomain("openpref.sourceforge.net");
QCoreApplication::setApplicationName("OpenPref");
#if !defined(WIN32) && !defined(_WIN32)
char *e = getenv("DEBUG");
if (!(!e || !strcmp(e, "0") || !strcasecmp(e, "off") || strcasecmp(e, "on"))) allowDebugLog = 1;
#endif
for (int f = 1; f < argc; f++) {
if (!strcmp(argv[f], "-d")) {
for (int c = f; c < argc; c++) argv[c] = argv[c+1];
argc--;
f--;
allowDebugLog = 1;
} else if (!strcmp(argv[f], "-o")) {
optAlphaBeta1 = false;
optAlphaBeta2 = false;
}
}
qsrand((unsigned)time(0));
QApplication a(argc, argv);
QString translationCode = QLocale::system().name();
QString qtFilename = QString(i18n_PATH) + "/openpref_" + translationCode + ".qm";
QTranslator qtTranslator(0);
qtTranslator.load(qtFilename);
a.installTranslator(&qtTranslator);
//a.setFont (QFont("helvetica", FONTSIZE));
kpref = new Kpref();
formBid = new FormBid(kpref);
formBid->hide();
kpref->init();
kpref->show();
bool exitCode = a.exec();
return exitCode;
}
openpref-0.1.3/src/main.pri 0000755 0001750 0001750 00000000716 11265177055 015206 0 ustar kostya kostya DEPENDPATH += $$PWD
INCLUDEPATH += $$PWD
HEADERS += \
$$PWD/kpref.h \
$$PWD/prfconst.h \
$$PWD/main.h
SOURCES += \
$$PWD/kpref.cpp \
$$PWD/prfconst.cpp \
$$PWD/main.cpp
FORMS += \
$$PWD/ui/optform.ui \
$$PWD/ui/newgameform.ui \
$$PWD/ui/helpbrowser.ui
include($$PWD/util/util.pri)
include($$PWD/cardutil/cardutil.pri)
include($$PWD/forms/forms.pri)
include($$PWD/score/score.pri)
include($$PWD/logic/logic.pri)
include($$PWD/desk/desk.pri)
openpref-0.1.3/src/prfconst.h 0000755 0001750 0001750 00000005405 11265177055 015555 0 ustar kostya kostya /*
* OpenPref - cross-platform Preferans game
*
* Copyright (C) 2000-2009 OpenPref Developers
* (see file AUTHORS for more details)
* Contact: annulen@users.sourceforge.net
*
* OpenPref is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (see file COPYING); if not, see
* http://www.gnu.org/licenses
*/
#ifndef PRFCONST_H
#define PRFCONST_H
#include
#include
typedef QList QIntList;
//typedef QList QIntList;
// choose card size:
// standard deck
/*
#define CARDWIDTH 71
#define CARDHEIGHT 96
*/
/*
// PrefClub deck
#define CARDWIDTH 56
#define CARDHEIGHT 67
*/
extern int CARDWIDTH;
extern int CARDHEIGHT;
#define FONTSIZE 10
#define SUIT_OFFSET 22
#define NEW_SUIT_OFFSET ((CARDWIDTH)+8)
#define CLOSED_CARD_OFFSET ((CARDWIDTH)*0.55)
//#define PEVENTMILLISECOND 50
#define CARDINCOLODA 32
#define MAXMASTLEN 8
#define MAXGAMELEN 1024
enum eHand {
LeftHand=0,
RightHand,
NoHand
};
enum eSuit {
SuitSpades=1,
SuitClubs,
SuitDiamonds,
SuitHearts,
SuitNone,
};
enum eGameBid {
zerogame=0,
showpool=1,
g86catch=56,
raspass=57,
whist=58,
halfwhist=59,
undefined=55,
withoutThree=54,
gtPass=60,
g61=61,g62,g63,g64,g65,
g71=71,g72,g73,g74,g75,
g81=81,g82,g83,g84,g85,g86,
g91=91,g92,g93,g94,g95,
g101=101,g102,g103,g104,g105
};// g86 - miser
typedef struct {
int tricks;
int perehvatov;
int len;
int sum;
} tSuitProbs;
extern bool optStalingrad;
extern bool opt10Whist;
extern bool optWhistGreedy;
extern int optMaxPool;
extern QString optHumanName;
extern QString optPlayerName1;
extern bool optAlphaBeta1;
extern QString optPlayerName2;
extern bool optAlphaBeta2;
extern bool optDebugHands;
extern eGameBid gCurrentGame;
extern bool optAggPass;
extern int optPassCount;
extern bool optWithoutThree;
extern bool optDealAnim;
extern bool optTakeAnim;
extern bool optPrefClub;
int succBid (eGameBid game);
const QString &sGameName (eGameBid game);
int trumpSuit ();
int gameTricks (eGameBid gType);
int gameWhists (eGameBid gType);
int gameWhistsMin (eGameBid gType);
int gamePoolPrice (eGameBid gType);
eGameBid gameName2Type (const QString &s);
#endif
openpref-0.1.3/src/cardutil/ 0000755 0001750 0001750 00000000000 11265437521 015343 5 ustar kostya kostya openpref-0.1.3/src/cardutil/card.h 0000755 0001750 0001750 00000004154 11265177055 016437 0 ustar kostya kostya /*
* OpenPref - cross-platform Preferans game
*
* Copyright (C) 2000-2009 OpenPref Developers
* (see file AUTHORS for more details)
* Contact: annulen@users.sourceforge.net
*
* OpenPref is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (see file COPYING); if not, see
* http://www.gnu.org/licenses
*/
#ifndef CARD_H
#define CARD_H
#include
#include
const int FACE_JACK = 11;
const int FACE_QUEEN = 12;
const int FACE_KING = 13;
const int FACE_ACE = 14;
class Card {
public:
inline int face () const { return mFace; }
inline int suit () const { return mSuit; }
inline bool isValid () const { return mValid; }
int pack () const;
QString toString () const;
friend int operator > (const Card &c0, const Card &c1);
friend int operator < (const Card &c0, const Card &c1);
friend int operator >= (const Card &c0, const Card &c1);
friend int operator <= (const Card &c0, const Card &c1);
friend int operator == (const Card &c0, const Card &c1);
friend int operator != (const Card &c0, const Card &c1);
friend Card *newCard (int aFace, int aSuit);
friend void initCardList ();
private:
void validate ();
int compareWith (const Card &c1) const;
Card (int aFace, int aSuit);
~Card ();
private:
int mFace; // 7,8,9,10,11j,12q,13k,14a
int mSuit; // 1 4
bool mValid;
};
typedef QList QCardList;
void initCardList ();
Card *newCard (int aFace, int aSuit);
Card *newCard (int aPacked);
Card *cardFromName (const char *str);
#endif
openpref-0.1.3/src/cardutil/card.cpp 0000755 0001750 0001750 00000007676 11265177055 017006 0 ustar kostya kostya /*
* OpenPref - cross-platform Preferans game
*
* Copyright (C) 2000-2009 OpenPref Developers
* (see file AUTHORS for more details)
* Contact: annulen@users.sourceforge.net
*
* OpenPref is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (see file COPYING); if not, see
* http://www.gnu.org/licenses
*/
#include "card.h"
Card::Card (int aFace, int aSuit) {
mFace = aFace;
mSuit = aSuit;
validate();
}
Card::~Card () {
}
void Card::validate () {
mValid = (mFace >= 7 && mFace <= 14 && mSuit >= 1 && mSuit <= 4);
}
int Card::pack () const {
if (!mValid) return 0;
return mFace*10+mSuit;
}
int Card::compareWith (const Card &c1) const {
int r = mSuit-c1.mSuit;
if (!r) r = mFace-c1.mFace;
return r;
}
QString Card::toString () const {
QString res("???");
if (!mValid) return res;
switch (mFace) {
case 7: res = " 7"; break;
case 8: res = " 8"; break;
case 9: res = " 9"; break;
case 10: res = "10"; break;
case 11: res = " J"; break;
case 12: res = " Q"; break;
case 13: res = " K"; break;
case 14: res = " A"; break;
default: return res;
}
switch (mSuit) {
case 1: res += "s"; break;
case 2: res += "c"; break;
case 3: res += "d"; break;
case 4: res += "h"; break;
default: res = "???";
}
return res;
}
///////////////////////////////////////////////////////////////////////////////
int operator > (const Card &c0, const Card &c1) {
return (c0.compareWith(c1) > 0) ? 1 : 0;
}
int operator < (const Card &c0, const Card &c1) {
return (c0.compareWith(c1) < 0) ? 1 : 0;
}
int operator >= (const Card &c0, const Card &c1) {
return (c0.compareWith(c1) >= 0) ? 1 : 0;
}
int operator <= (const Card &c0, const Card &c1) {
return (c0.compareWith(c1) <= 0) ? 1 : 0;
}
int operator == (const Card &c0, const Card &c1) {
return (c0.compareWith(c1) == 0) ? 1 : 0;
}
int operator != (const Card &c0, const Card &c1) {
return (c0.compareWith(c1) != 0) ? 1 : 0;
}
///////////////////////////////////////////////////////////////////////////////
static Card *cList[33];
static bool inited = false;
void initCardList () {
if (inited) return;
for (int f = 0; f < 32; f++) cList[f] = new Card(f/4+7, f%4+1);
/*
cList[32] = new Card(7, 1);
cList[32]->mFace = 0;
cList[32]->mSuit = 0;
cList[32]->mValid = false;
*/
cList[32] = 0;
inited = true;
}
Card *newCard (int aFace, int aSuit) {
initCardList();
int no = 32;
if (aFace >= 7 && aFace <= FACE_ACE && aSuit >= 1 && aSuit <= 4) no = (aFace-7)*4+(aSuit-1);
return cList[no];
}
Card *cardFromName (const char *str) {
int face = -1, suit = -1;
if (!str) return 0;
while (*str && (unsigned char)(*str) <= ' ') str++;
switch (*str++) {
case '7': face = 7; break;
case '8': face = 8; break;
case '9': face = 9; break;
case '1':
if (*str++ != '0') return 0;
face = 10;
break;
case 'J': case 'j': face = 11; break;
case 'Q': case 'q': face = 12; break;
case 'K': case 'k': face = 13; break;
case 'A': case 'a': face = 14; break;
default: return 0;
}
while (*str && (unsigned char)(*str) <= ' ') str++;
switch (*str++) {
case 'S': case 's': suit = 1; break;
case 'C': case 'c': suit = 2; break;
case 'D': case 'd': suit = 3; break;
case 'H': case 'h': suit = 4; break;
default: return 0;
}
return newCard(face, suit);
}
openpref-0.1.3/src/cardutil/cardlist.h 0000755 0001750 0001750 00000006211 11265177055 017327 0 ustar kostya kostya /*
* OpenPref - cross-platform Preferans game
*
* Copyright (C) 2000-2009 OpenPref Developers
* (see file AUTHORS for more details)
* Contact: annulen@users.sourceforge.net
*
* OpenPref is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (see file COPYING); if not, see
* http://www.gnu.org/licenses
*/
//---------------------------------------------------------------------------
#ifndef CARDLIST_H
#define CARDLIST_H
#include
#include "prfconst.h"
#include "card.h"
// doesn't own the cards
class CardList {
public:
CardList ();
CardList (const CardList &cl);
~CardList ();
void clear ();
void mySort ();
Card *exists (int aFace, int aSuit) const;
Card *exists (Card *cc) const;
Card *minInSuit (int aSuit) const;
Card *maxInSuit (int aSuit) const;
Card *minFace () const;
Card *maxFace () const;
bool hasSuit (int aSuit) const;
Card *greaterInSuit (int aFace, int aSuit) const; //
Card *lesserInSuit (int aFace, int aSuit) const; //
Card *greaterInSuit (Card *card) const; //
Card *lesserInSuit (Card *card) const; //
void copySuit (const CardList *src, eSuit aSuit); // copy only selected suit
int cardsInSuit (int aSuit) const;
int count () const;
int emptySuit (int aSuit) const; // ( )
inline int indexOf (Card *cc) const {
if (!cc) return -1;
return mList.indexOf(cc);
}
inline Card *at (int idx) const {
if (idx < 0 || idx >= mList.size()) return 0;
return mList[idx];
}
inline void putAt (int idx, Card *c) {
if (idx < 0) return;
while (idx >= mList.size()) mList << 0;
mList[idx] = c;
}
inline void removeAt (int idx) { if (idx >= 0 && idx < mList.size()) mList[idx] = 0; }
inline void remove (Card *c) { removeAt(mList.indexOf(c)); }
inline int insert (Card *c) {
int idx = mList.indexOf(0);
if (idx < 0) {
idx = mList.size();
mList << c;
} else mList[idx] = c;
return idx;
}
inline int size () const { return mList.size(); }
void serialize (QByteArray &ba) const;
bool unserialize (QByteArray &ba, int *pos);
CardList &operator = (const CardList &cl);
CardList &operator = (const CardList *cl);
CardList &operator << (Card *cc);
void newDeck ();
void shuffle ();
protected:
//void removeNulls ();
void shallowCopy (const CardList *list);
void shallowCopy (const CardList &list);
protected:
QCardList mList;
};
#endif
openpref-0.1.3/src/cardutil/cardutil.cmake 0000644 0001750 0001750 00000000257 11265177055 020163 0 ustar kostya kostya project(openpref)
SET ( HEADERS ${HEADERS}
src/cardutil/card.h
src/cardutil/cardlist.h
)
SET ( SOURCES ${SOURCES}
src/cardutil/card.cpp
src/cardutil/cardlist.cpp
) openpref-0.1.3/src/cardutil/cardutil.pri 0000755 0001750 0001750 00000000221 11265177055 017667 0 ustar kostya kostya DEPENDPATH += $$PWD
INCLUDEPATH += $$PWD
HEADERS += \
$$PWD/card.h \
$$PWD/cardlist.h
SOURCES += \
$$PWD/card.cpp \
$$PWD/cardlist.cpp
openpref-0.1.3/src/cardutil/cardlist.cpp 0000755 0001750 0001750 00000013756 11265177055 017676 0 ustar kostya kostya /*
* OpenPref - cross-platform Preferans game
*
* Copyright (C) 2000-2009 OpenPref Developers
* (see file AUTHORS for more details)
* Contact: annulen@users.sourceforge.net
*
* OpenPref is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (see file COPYING); if not, see
* http://www.gnu.org/licenses
*/
#include "cardlist.h"
#include "baser.h"
CardList::CardList () {
}
CardList::CardList (const CardList &cl) {
shallowCopy(cl);
}
CardList::~CardList () {
clear();
}
void CardList::clear () {
mList.clear();
}
Card *CardList::exists (int aFace, int aSuit) const {
Card *c = newCard(aFace, aSuit);
return exists(c);
}
// can compare pointers, 'cause cards are singletones
Card *CardList::exists (Card *cc) const {
if (!cc) return 0;
if (mList.indexOf(cc) >= 0) return cc;
return 0;
}
Card *CardList::minFace () const {
return minInSuit(-1);
}
Card *CardList::maxFace () const {
return maxInSuit(-1);
}
Card *CardList::minInSuit (int aSuit) const {
Card *res = 0;
foreach (Card *c, mList) {
if (!c) continue;
if (aSuit > 0 && c->suit() != aSuit) continue;
if (!res || res->face() > c->face()) res = c;
}
return res;
}
Card * CardList::maxInSuit (int aSuit) const {
Card *res = 0;
foreach (Card *c, mList) {
if (!c) continue;
if (aSuit > 0 && c->suit() != aSuit) continue;
if (!res || res->face() < c->face()) res = c;
}
return res;
}
int CardList::cardsInSuit (int aSuit) const {
int res = 0;
foreach (Card *c, mList) if (c && c->suit() == aSuit) res++;
return res;
}
int CardList::count () const {
int res = 0;
foreach (Card *c, mList) if (c) res++;
return res;
}
void CardList::mySort () {
int cnt = mList.size();
// bubble sort
for (int f = 0; f < cnt; f++) {
for (int c = cnt-1; c > f; c--) {
Card *cf = mList[f], *cc = mList[c];
if (cf || cc) {
int r = 0;
if (cf && cc) {
r = (cf->suit())-(cc->suit());
if (!r) r = (cc->face())-(cf->face());
} else if (!cf) r = 1; // so nulls will go down
if (r > 0) mList.swap(f, c);
} else {
// both empty
}
}
}
}
Card *CardList::greaterInSuit (int aFace, int aSuit) const {
if (aFace > FACE_ACE) return 0;
if (aFace < 7) aFace = 7;
while (aFace <= FACE_ACE) {
Card *found = exists(aFace, aSuit);
if (found) return found;
aFace++;
}
return 0;
}
Card *CardList::greaterInSuit (Card *card) const {
if (!card) return 0;
return greaterInSuit(card->face(), card->suit());
}
Card *CardList::lesserInSuit (int aFace, int aSuit) const {
if (aFace < 7) return 0;
if (aFace > FACE_ACE) aFace = FACE_ACE;
while (aFace >= 7) {
Card *found = exists(aFace, aSuit);
if (found) return found;
aFace--;
}
return 0;
}
//
Card *CardList::lesserInSuit (Card *card) const {
if (!card) return 0;
return lesserInSuit(card->face(), card->suit());
}
bool CardList::hasSuit (int aSuit) const {
foreach (Card *c, mList) {
if (c && c->suit() == aSuit) return true;
}
return false;
}
int CardList::emptySuit (int aSuit) const {
for (int f = 1; f <= 4; f++) {
if (f == aSuit) continue; //k8:bug? break;
if (!hasSuit(f)) return f;
}
return 0;
}
void CardList::copySuit (const CardList *src, eSuit aSuit) {
// remove existing cards
/*
QMutableListIterator i(mList);
while (i.hasNext()) {
Card *c = i.next();
if (c->suit() == (int)aSuit) i.remove();
}
*/
for (int f = mList.size()-1; f >= 0; f--) {
Card *c = mList[f];
if (c && c->suit() == aSuit) mList[f] = 0;
}
// copy cards
foreach (Card *c, src->mList) {
if (c && c->suit() == (int)aSuit) insert(c);
}
}
void CardList::shallowCopy (const CardList *list) {
clear();
if (!list) return;
foreach (Card *c, list->mList) mList << c;
}
void CardList::shallowCopy (const CardList &list) {
clear();
foreach (Card *c, list.mList) mList << c;
}
void CardList::serialize (QByteArray &ba) const {
serializeInt(ba, mList.size());
for (int f = 0; f < mList.size(); f++) {
Card *c = mList[f];
int i = 0;
if (c) i = (c->face()-7)*10+c->suit();
serializeInt(ba, i);
}
}
bool CardList::unserialize (QByteArray &ba, int *pos) {
clear();
int cnt;
if (!unserializeInt(ba, pos, &cnt)) return false;
while (cnt-- > 0) {
int t;
if (!unserializeInt(ba, pos, &t)) return false;
if (t < 1 || t > 74) t = 0;
if (t) {
int face = (t/10)+7, suit = t%10;
if (face >= 7 && face <= FACE_ACE && suit >= 1 && suit <= 4) mList << newCard(face, suit);
else mList << 0;
} else mList << 0;
}
return true;
}
CardList &CardList::operator = (const CardList &cl) {
if (&cl != this) shallowCopy(cl);
return *this;
}
CardList &CardList::operator = (const CardList *cl) {
if (cl != this) shallowCopy(cl);
return *this;
}
CardList &CardList::operator << (Card *cc) {
if (cc) insert(cc);
return *this;
}
void CardList::newDeck () {
mList.clear();
for (int suit = 1; suit <= 4; suit++) {
for (int face = 7; face <= FACE_ACE; face++) {
mList << newCard(face, suit);
}
}
}
void CardList::shuffle () {
// remove nulls
QMutableListIterator i(mList);
while (i.hasNext()) {
Card *c = i.next();
if (!c) i.remove();
}
// Fisher-Yates shuffler
for (int f = mList.size()-1; f >= 0; f--) {
int n = (qrand()/256)%(f+1); // 0<=n<=f
mList.swap(f, n);
}
}
openpref-0.1.3/src/main.h 0000755 0001750 0001750 00000002201 11265177055 014632 0 ustar kostya kostya /*
* OpenPref - cross-platform Preferans game
*
* Copyright (C) 2000-2009 OpenPref Developers
* (see file AUTHORS for more details)
* Contact: annulen@users.sourceforge.net
*
* OpenPref is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (see file COPYING); if not, see
* http://www.gnu.org/licenses
*/
#ifndef MAIN_H
#define MAIN_H
#include
#include "prfconst.h"
#include "kpref.h"
/*class OpenPrefApp : public QApplication {
Q_OBJECT
public:
OpenPrefApp();
~OpenPrefApp();
}*/
#endif
openpref-0.1.3/src/src.cmake 0000644 0001750 0001750 00000001627 11265177055 015336 0 ustar kostya kostya project(openpref)
INCLUDE_DIRECTORIES( src )
SET ( HEADERS ${HEADERS}
src/kpref.h
src/prfconst.h
src/main.h
)
SET ( SOURCES ${SOURCES}
src/kpref.cpp
src/prfconst.cpp
src/main.cpp
)
SET ( UIS ${UIS}
src/ui/optform.ui
src/ui/newgameform.ui
src/ui/helpbrowser.ui
)
# tell cmake to process CMakeLists.txt in that subdirectory
#add_subdirectory(util)
#add_subdirectory(cardutil)
#add_subdirectory(forms)
#add_subdirectory(score)
#add_subdirectory(logic)
#add_subdirectory(desk)
include(src/util/util.cmake)
include(src/cardutil/cardutil.cmake)
include(src/forms/forms.cmake)
include(src/score/score.cmake)
include(src/logic/logic.cmake)
include(src/desk/desk.cmake)
INCLUDE_DIRECTORIES( src )
INCLUDE_DIRECTORIES( src/util )
INCLUDE_DIRECTORIES( src/cardutil )
INCLUDE_DIRECTORIES( src/forms )
INCLUDE_DIRECTORIES( src/score )
INCLUDE_DIRECTORIES( src/logic )
INCLUDE_DIRECTORIES( src/desk )
openpref-0.1.3/BUGS 0000644 0001750 0001750 00000000172 11265177055 013433 0 ustar kostya kostya Known Issues
1. AI algorithm for choose of maximum bid is not perfect
2. "Save" menu saves only score, not cards in hands openpref-0.1.3/NEWS 0000644 0001750 0001750 00000000546 11265177055 013454 0 ustar kostya kostya OpenPref 0.1.3
New game features:
* Closed whist
* Without three
* Improved old AI for misere and pass-out
* Fixed bug in bidding after pass-out
* Amnesty for pass-out
Other improvements
* Clean exit without sending abort()
* Two card decks are available
* Options (animation and card deck) can be changed game
* Save/open functionality
* Resizable window
openpref-0.1.3/TODO 0000644 0001750 0001750 00000000466 11265177055 013446 0 ustar kostya kostya For OpenPref 0.1.4:
* Improve bidding algorithm
* Refactoring for future network game support
* Add help system
* Start micro version for mobile devices
For OpenPref 0.2.0:
* Network game via XMPP protocol
* AI improvement
* Different AI's with their own bidding schemes
* Interactive help system
* Artwork openpref-0.1.3/pics/ 0000755 0001750 0001750 00000000000 11265437521 013703 5 ustar kostya kostya openpref-0.1.3/pics/xcf/ 0000755 0001750 0001750 00000000000 11265437521 014463 5 ustar kostya kostya openpref-0.1.3/pics/xcf/bidinfo.xcf 0000755 0001750 0001750 00000013213 11265177055 016605 0 ustar kostya kostya gimp xcf file S C B B 6
gimp-comment gimp-image-grid (style solid)
(fgcolor (color-rgba 0.000000 0.000000 0.000000 1.000000))
(bgcolor (color-rgba 1.000000 1.000000 1.000000 1.000000))
(xspacing 10.000000)
(yspacing 10.000000)
(spacing-unit inches)
(xoffset 0.000000)
(yoffset 0.000000)
(offset-unit inches)
S C Background
P S C h S C D P | 9 T7 T7 T#T T#T T$T T$T T$T T$T T$T T$T T$T T$T T$T T$T T$T T$T T$T T
T
TT TT
TT
TT TTT TTTT TTT TTT TTT TTT TT T TT!T TT"T TT# TT$ TT$ TT$ TT$ TT$ TT$ TT#T TT"T TT!T TT T TTT TTT TTT TTTTTTT TTTTT TTTTTT TTTT
T TT T T
TT
TT* TT* T
T, TT. TT. TT0 TT2 TT2 T4 T8 TT7 T6 T2 TTTT, 9 9 T8 T%T %T T%T T%T T%T T%T T%T T%T T%T T%T T%T T%T T%T T%T T%T T!
T
TT TT
TT
TT TTT TTTT TTT TTT TTT TTT TT T TT!T TT"T TT# TT$ TT$ TT$ TT$ TT$ TT$ TT#T TT"T TT!T TT T TTT TTT TTT TTTTTTT TTTTT TTTTTT TTTT
T TT T T
TT
T
T* TT* TT, T T. TT. TT0 TT2 TT2 T4 T9 T8 T7 T6 T, 9T T7 T ; T # T T # T T $ T T $ T T $ T T $ T T $ T T $ T T $ T T $ T T $ T T $ T T $ T T $ T T $ T T
T T T TT
T T
TT
T T T T T TT T T T T T T T T T T T T T T T T T ! T T T " T T T # T T $ T T $ T T $ T T $ T T $ T T $ T T # T T T " T T T ! T T T T T T T T T T T T T T T TT T TT T T T T T T T TT T T T T TT
T T T T T
T T
T T- T T - T
T / T T1 T T 1 T T 3 T T5 T T 5 T 7 T ; TT ; T ; T8 TTTTT, 9 8 9 : ; ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<; : 9 TTTTTTTTT
TTTT TTTTTT TT
T T
T TTTTTTTTTTTT
TTTT TTTTTT TT
T
T T TT T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T TT
T T T T T TT T T T T T TT T T T T T TT T
T T T
T
T ^
T6T T6T 8T 8 ; :T ) T )
T*
) ! S C Selection Mask S C 6 S C R T e q D <