mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-10-01 02:35:48 -04:00
452 lines
12 KiB
C++
452 lines
12 KiB
C++
|
/***************************************************************************
|
||
|
* Copyright (C) 2002-2003 Andi Peredri *
|
||
|
* andi@ukr.net *
|
||
|
* *
|
||
|
* This program 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 2 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; if not, write to the *
|
||
|
* Free Software Foundation, Inc., *
|
||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||
|
***************************************************************************/
|
||
|
//
|
||
|
// KCheckers Engine
|
||
|
|
||
|
//
|
||
|
// Internal: External:
|
||
|
//
|
||
|
// Board = 54 Fields: Board = 32 Fields:
|
||
|
//
|
||
|
// | 06 07 08 09| MAN2 | 00 01 02 03|
|
||
|
// |11 12 13 14 | |04 05 06 07 |
|
||
|
// | 17 18 19 20| | 08 09 10 11|
|
||
|
// |22 23 24 25 | |12 13 14 15 |
|
||
|
// | 28 29 30 31| | 16 17 18 19|
|
||
|
// |33 34 35 36 | |20 21 22 23 |
|
||
|
// | 39 40 41 42| | 24 25 26 27|
|
||
|
// |44 45 46 47 | MAN1 |28 29 30 31 |
|
||
|
|
||
|
#include <time.h>
|
||
|
#include <stdlib.h>
|
||
|
|
||
|
#include <QDebug>
|
||
|
|
||
|
#include "checkers.h"
|
||
|
|
||
|
|
||
|
int Checkers::internal(int external) const
|
||
|
{
|
||
|
const int i[]={6,7,8,9,11,12,13,14,17,18,19,20,22,23,24,25,
|
||
|
28,29,30,31,33,34,35,36,39,40,41,42,44,45,46,47};
|
||
|
return i[external];
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
int Checkers::external(int internal) const
|
||
|
{
|
||
|
const int i[]={
|
||
|
-1,-1,-1,-1,-1,-1,0,1,2,3, // 0-9 internal
|
||
|
-1,4,5,6,7,-1,-1,8,9,10, // 10-19
|
||
|
11,-1,12,13,14,15,-1,-1,16,17, // 20-29
|
||
|
18,19,-1,20,21,22,23,-1,-1,24, // 30-39
|
||
|
25,26,27,-1,28,29,30,31,-1,-1, // 40-49
|
||
|
-1,-1,-1,-1}; // 50-53
|
||
|
return i[internal];
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
|
||
|
Checkers::Checkers()
|
||
|
{
|
||
|
for(int i=0;i<54;i++) board[i] = NONE;
|
||
|
|
||
|
for(int i=0; i<12; i++) board[internal(i)] = MAN2;
|
||
|
for(int i=12; i<20; i++) board[internal(i)] = FREE;
|
||
|
for(int i=20; i<32; i++) board[internal(i)] = MAN1;
|
||
|
|
||
|
levelmax = 2;
|
||
|
|
||
|
srand(time(0)); // Seed the random number generator
|
||
|
}
|
||
|
|
||
|
|
||
|
bool Checkers::setup(int setupboard[])
|
||
|
{
|
||
|
/*aw - caused problems
|
||
|
int sum1=0; // Sum of MAN1 & KING1
|
||
|
int sum2=0; // Sum of MAN2 & KING2
|
||
|
|
||
|
for(int i=0; i<32; i++) {
|
||
|
switch(setupboard[i]) {
|
||
|
case MAN1:
|
||
|
case KING1: sum1++; break;
|
||
|
case MAN2:
|
||
|
case KING2: sum2++; break;
|
||
|
|
||
|
case FREE: break;
|
||
|
|
||
|
default: return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(sum1>12 || sum1==0 || sum2>12 || sum2==0)
|
||
|
return false;
|
||
|
|
||
|
for(int i=0; i<4; i++)
|
||
|
if(setupboard[i]==MAN1) return false;
|
||
|
|
||
|
for(int i=28; i<32; i++)
|
||
|
if(setupboard[i]==MAN2) return false;
|
||
|
*/
|
||
|
|
||
|
for(int i=0; i<32; i++)
|
||
|
board[internal(i)] = setupboard[i];
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////
|
||
|
//
|
||
|
// Player Functions
|
||
|
//
|
||
|
///////////////////////////////////////////////////
|
||
|
|
||
|
|
||
|
bool Checkers::checkMove1() const
|
||
|
{
|
||
|
for(int i=6;i<48;i++)
|
||
|
if(checkMove1(i))
|
||
|
return true;
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
|
||
|
bool Checkers::checkMove1(int i) const
|
||
|
{
|
||
|
switch(board[i]) {
|
||
|
case MAN1:
|
||
|
if(board[i-6]==FREE) return true;
|
||
|
if(board[i-5]==FREE) return true;
|
||
|
break;
|
||
|
case KING1:
|
||
|
if(board[i-6]==FREE) return true;
|
||
|
if(board[i-5]==FREE) return true;
|
||
|
if(board[i+5]==FREE) return true;
|
||
|
if(board[i+6]==FREE) return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Computer Functions
|
||
|
//
|
||
|
////////////////////////////////////////////////////
|
||
|
|
||
|
|
||
|
void Checkers::go2()
|
||
|
{
|
||
|
//
|
||
|
level=0;
|
||
|
for(int i=6;i<48;i++)
|
||
|
bestboard[i] = board[i];
|
||
|
turn();
|
||
|
for(int i=6;i<48;i++)
|
||
|
board[i] = bestboard[i];
|
||
|
;
|
||
|
}
|
||
|
|
||
|
|
||
|
void Checkers::turn(int& resMax, bool capture)
|
||
|
{
|
||
|
if(level<levelmax) {
|
||
|
bool f12, f13, f14, f17, f18, f19, f23, f24, f25;
|
||
|
bool f28, f29, f30, f34, f35, f36, f39, f40, f41;
|
||
|
f12 = f13 = f14 = f17 = f18 = f19 = f23 = f24 = f25 = false;//for gcc
|
||
|
f28 = f29 = f30 = f34 = f35 = f36 = f39 = f40 = f41 = false;//for gcc
|
||
|
|
||
|
if(capture) {
|
||
|
if(board[12]==NONE) {f12=true; board[12] = FREE;} else f12=false;
|
||
|
if(board[13]==NONE) {f13=true; board[13] = FREE;} else f13=false;
|
||
|
if(board[14]==NONE) {f14=true; board[14] = FREE;} else f14=false;
|
||
|
if(board[17]==NONE) {f17=true; board[17] = FREE;} else f17=false;
|
||
|
if(board[18]==NONE) {f18=true; board[18] = FREE;} else f18=false;
|
||
|
if(board[19]==NONE) {f19=true; board[19] = FREE;} else f19=false;
|
||
|
if(board[23]==NONE) {f23=true; board[23] = FREE;} else f23=false;
|
||
|
if(board[24]==NONE) {f24=true; board[24] = FREE;} else f24=false;
|
||
|
if(board[25]==NONE) {f25=true; board[25] = FREE;} else f25=false;
|
||
|
if(board[28]==NONE) {f28=true; board[28] = FREE;} else f28=false;
|
||
|
if(board[29]==NONE) {f29=true; board[29] = FREE;} else f29=false;
|
||
|
if(board[30]==NONE) {f30=true; board[30] = FREE;} else f30=false;
|
||
|
if(board[34]==NONE) {f34=true; board[34] = FREE;} else f34=false;
|
||
|
if(board[35]==NONE) {f35=true; board[35] = FREE;} else f35=false;
|
||
|
if(board[36]==NONE) {f36=true; board[36] = FREE;} else f36=false;
|
||
|
if(board[39]==NONE) {f39=true; board[39] = FREE;} else f39=false;
|
||
|
if(board[40]==NONE) {f40=true; board[40] = FREE;} else f40=false;
|
||
|
if(board[41]==NONE) {f41=true; board[41] = FREE;} else f41=false;
|
||
|
}
|
||
|
|
||
|
int b6=board[6];
|
||
|
int b7=board[7];
|
||
|
int b8=board[8];
|
||
|
int b9=board[9];
|
||
|
int b11=board[11];
|
||
|
int b12=board[12];
|
||
|
int b13=board[13];
|
||
|
int b14=board[14];
|
||
|
int b17=board[17];
|
||
|
int b18=board[18];
|
||
|
int b19=board[19];
|
||
|
int b20=board[20];
|
||
|
int b22=board[22];
|
||
|
int b23=board[23];
|
||
|
int b24=board[24];
|
||
|
int b25=board[25];
|
||
|
int b28=board[28];
|
||
|
int b29=board[29];
|
||
|
int b30=board[30];
|
||
|
int b31=board[31];
|
||
|
int b33=board[33];
|
||
|
int b34=board[34];
|
||
|
int b35=board[35];
|
||
|
int b36=board[36];
|
||
|
int b39=board[39];
|
||
|
int b40=board[40];
|
||
|
int b41=board[41];
|
||
|
int b42=board[42];
|
||
|
int b44=board[44];
|
||
|
int b45=board[45];
|
||
|
int b46=board[46];
|
||
|
int b47=board[47];
|
||
|
|
||
|
board[6]=FULL-b47;
|
||
|
board[7]=FULL-b46;
|
||
|
board[8]=FULL-b45;
|
||
|
board[9]=FULL-b44;
|
||
|
board[11]=FULL-b42;
|
||
|
board[12]=FULL-b41;
|
||
|
board[13]=FULL-b40;
|
||
|
board[14]=FULL-b39;
|
||
|
board[17]=FULL-b36;
|
||
|
board[18]=FULL-b35;
|
||
|
board[19]=FULL-b34;
|
||
|
board[20]=FULL-b33;
|
||
|
board[22]=FULL-b31;
|
||
|
board[23]=FULL-b30;
|
||
|
board[24]=FULL-b29;
|
||
|
board[25]=FULL-b28;
|
||
|
board[28]=FULL-b25;
|
||
|
board[29]=FULL-b24;
|
||
|
board[30]=FULL-b23;
|
||
|
board[31]=FULL-b22;
|
||
|
board[33]=FULL-b20;
|
||
|
board[34]=FULL-b19;
|
||
|
board[35]=FULL-b18;
|
||
|
board[36]=FULL-b17;
|
||
|
board[39]=FULL-b14;
|
||
|
board[40]=FULL-b13;
|
||
|
board[41]=FULL-b12;
|
||
|
board[42]=FULL-b11;
|
||
|
board[44]=FULL-b9;
|
||
|
board[45]=FULL-b8;
|
||
|
board[46]=FULL-b7;
|
||
|
board[47]=FULL-b6;
|
||
|
|
||
|
int res=-turn();
|
||
|
|
||
|
board[6]=b6;
|
||
|
board[7]=b7;
|
||
|
board[8]=b8;
|
||
|
board[9]=b9;
|
||
|
board[11]=b11;
|
||
|
board[12]=b12;
|
||
|
board[13]=b13;
|
||
|
board[14]=b14;
|
||
|
board[17]=b17;
|
||
|
board[18]=b18;
|
||
|
board[19]=b19;
|
||
|
board[20]=b20;
|
||
|
board[22]=b22;
|
||
|
board[23]=b23;
|
||
|
board[24]=b24;
|
||
|
board[25]=b25;
|
||
|
board[28]=b28;
|
||
|
board[29]=b29;
|
||
|
board[30]=b30;
|
||
|
board[31]=b31;
|
||
|
board[33]=b33;
|
||
|
board[34]=b34;
|
||
|
board[35]=b35;
|
||
|
board[36]=b36;
|
||
|
board[39]=b39;
|
||
|
board[40]=b40;
|
||
|
board[41]=b41;
|
||
|
board[42]=b42;
|
||
|
board[44]=b44;
|
||
|
board[45]=b45;
|
||
|
board[46]=b46;
|
||
|
board[47]=b47;
|
||
|
|
||
|
if(res>resMax) {
|
||
|
resMax=res;
|
||
|
if(level==1) {
|
||
|
for(int i=6;i<48;i++) bestboard[i]=board[i];
|
||
|
bestcounter=1;
|
||
|
}
|
||
|
} else if(res==resMax && level==1) {
|
||
|
bestcounter++;
|
||
|
if((rand()%bestcounter)==0) {
|
||
|
for(int i=6;i<48;i++) bestboard[i]=board[i];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(capture) {
|
||
|
if(f12) board[12]=NONE;
|
||
|
if(f13) board[13]=NONE;
|
||
|
if(f14) board[14]=NONE;
|
||
|
if(f17) board[17]=NONE;
|
||
|
if(f18) board[18]=NONE;
|
||
|
if(f19) board[19]=NONE;
|
||
|
if(f23) board[23]=NONE;
|
||
|
if(f24) board[24]=NONE;
|
||
|
if(f25) board[25]=NONE;
|
||
|
if(f28) board[28]=NONE;
|
||
|
if(f29) board[29]=NONE;
|
||
|
if(f30) board[30]=NONE;
|
||
|
if(f34) board[34]=NONE;
|
||
|
if(f35) board[35]=NONE;
|
||
|
if(f36) board[36]=NONE;
|
||
|
if(f39) board[39]=NONE;
|
||
|
if(f40) board[40]=NONE;
|
||
|
if(f41) board[41]=NONE;
|
||
|
}
|
||
|
}
|
||
|
else if(resMax<0) resMax=0;
|
||
|
}
|
||
|
|
||
|
|
||
|
bool Checkers::checkMove2() const
|
||
|
{
|
||
|
for(int i=6;i<48;i++) {
|
||
|
switch(board[i]) {
|
||
|
case MAN2:
|
||
|
if(board[i+5]==FREE) return true;
|
||
|
if(board[i+6]==FREE) return true;
|
||
|
break;
|
||
|
case KING2:
|
||
|
if(board[i-6]==FREE) return true;
|
||
|
if(board[i-5]==FREE) return true;
|
||
|
if(board[i+5]==FREE) return true;
|
||
|
if(board[i+6]==FREE) return true;
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
|
||
|
int Checkers::turn()
|
||
|
{
|
||
|
int resMax=(level-levelmax)*10;
|
||
|
level++;
|
||
|
|
||
|
if(checkCapture2()) {
|
||
|
for(int i=6; i<48; i++) {
|
||
|
switch(board[i]) {
|
||
|
case MAN2:
|
||
|
manCapture2(i, resMax);
|
||
|
break;
|
||
|
case KING2:
|
||
|
kingCapture2(i,UL,resMax);
|
||
|
kingCapture2(i,UR,resMax);
|
||
|
kingCapture2(i,DL,resMax);
|
||
|
kingCapture2(i,DR,resMax);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
} else if(checkMove2()) {
|
||
|
for(int i=6;i<48;i++) {
|
||
|
switch(board[i]) {
|
||
|
case MAN2:
|
||
|
if(board[i+5]==FREE) { // down left
|
||
|
board[i]=FREE;
|
||
|
if(i>38)
|
||
|
board[i+5]=KING2;
|
||
|
else
|
||
|
board[i+5]=MAN2;
|
||
|
turn(resMax);
|
||
|
board[i+5]=FREE;
|
||
|
board[i]=MAN2;
|
||
|
}
|
||
|
if(board[i+6]==FREE) { // down right
|
||
|
board[i]=FREE;
|
||
|
if(i>38)
|
||
|
board[i+6]=KING2;
|
||
|
else
|
||
|
board[i+6]=MAN2;
|
||
|
turn(resMax);
|
||
|
board[i+6]=FREE;
|
||
|
board[i]=MAN2;
|
||
|
}
|
||
|
break;
|
||
|
case KING2:
|
||
|
kingMove2(i,resMax);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
} else ;
|
||
|
|
||
|
level--;
|
||
|
return resMax;
|
||
|
}
|
||
|
|
||
|
|
||
|
QString Checkers::toString(bool rotate) const
|
||
|
{
|
||
|
int fields[32];
|
||
|
int it;
|
||
|
|
||
|
for(int i=0; i<32; i++) {
|
||
|
it = item(i);
|
||
|
if(rotate)
|
||
|
fields[31-i] = (~it&7)-1;
|
||
|
else
|
||
|
fields[i] = it;
|
||
|
}
|
||
|
|
||
|
QString str;
|
||
|
for(int i=0; i<32; i++)
|
||
|
str += QString("").sprintf("%.2u", fields[i]);
|
||
|
|
||
|
return str;
|
||
|
}
|
||
|
|
||
|
|
||
|
bool Checkers::fromString(const QString& str)
|
||
|
{
|
||
|
int fields[32];
|
||
|
|
||
|
for(int i=0; i<32; i++)
|
||
|
fields[i] = str.mid(i*2, 2).toInt();
|
||
|
|
||
|
// apply
|
||
|
if(!setup(fields)) {
|
||
|
qDebug() << "Checkers::fromString:" << str;
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|