mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-16 06:05:58 -06:00
277 lines
8.1 KiB
C++
277 lines
8.1 KiB
C++
#include "ataxx.h"
|
|
|
|
// bord.cpp
|
|
|
|
ataxxbord::ataxxbord (int aantalkolommen, int aantalrijen) {
|
|
// constructor
|
|
int i; // hulpvariabele voor iteratie
|
|
maxkolom = aantalkolommen; // onthoud maxkolom als afmeting
|
|
maxrij = aantalrijen; // onthoud maxrij als afmeting
|
|
// dynamische array maken
|
|
veld = new int * [maxkolom];
|
|
for (i=0;i<maxkolom;i++) {
|
|
veld[i] = new int [maxrij];
|
|
}
|
|
// en het bord in de beginstand zetten
|
|
beginstand();
|
|
}
|
|
|
|
ataxxbord::~ataxxbord() {
|
|
// destructor
|
|
int x; // hulpvariabele voor iteratie
|
|
for (x=0;x<maxkolom;x++) {
|
|
delete [] veld[x];
|
|
}
|
|
delete [] veld;
|
|
veld = NULL;
|
|
}
|
|
|
|
void ataxxbord::beginstand() {
|
|
// het speelbord in de beginstand zetten
|
|
// en startposities instellen
|
|
int x,y; // hulpvariabelen voor iteraties door veld
|
|
for (x=0;x<maxkolom;x++) {
|
|
for (y=0;y<maxrij;y++) {
|
|
veld[x][y] = 0;
|
|
}
|
|
}
|
|
veld[0][maxrij-1] = 1; // beginstand speler 1
|
|
veld[maxkolom-1][0] = 2; // beginstand speler 2
|
|
}
|
|
|
|
bool ataxxbord::toegestanezet (zet test) {
|
|
// als een zet toegestaan is, dan true retourneren
|
|
|
|
int dx, dy; // afstanden over x en y die een zet doet
|
|
|
|
// test 1: blijft de zet wel binnen het bord?
|
|
if ( test.xdoel > maxkolom-1 || test.ydoel > maxrij-1 ) return false;
|
|
if ( test.xdoel < 0 || test.ydoel < 0 ) return false;
|
|
|
|
// test 2: staat er op het bronveld wel een eigen virus?
|
|
if ( veld[test.xbron][test.ybron] != test.speler ) return false;
|
|
|
|
// test 3: is het doelvak wel vrij?
|
|
if ( veld[test.xdoel][test.ydoel] != 0 ) return false;
|
|
|
|
// test 4: afstand bron-doel moet 1 of 2 vakjes zijn, maar niet groter
|
|
dx = test.xdoel - test.xbron;
|
|
dy = test.ydoel - test.ybron;
|
|
// absolute waarden van maken
|
|
if ( dx < 0 ) dx *= -1;
|
|
if ( dy < 0 ) dy *= -1;
|
|
if ( dx > 2 || dy > 2 ) return false;
|
|
|
|
// als alle tests doorstaan zijn, is de zet toegestaan
|
|
return true;
|
|
}
|
|
|
|
void ataxxbord::doezet (zet doen) {
|
|
// voer een zet uit
|
|
|
|
int dx,dy,afstand; // afstanden over x en y die een zet doet
|
|
|
|
// nieuwe veld vullen met virus (zowel bij clonatie als verplaatsing)
|
|
veld[doen.xdoel][doen.ydoel] = doen.speler;
|
|
|
|
// aangrenzende (vijandige) virussen overnemen
|
|
for ( dx=doen.xdoel-1; dx<=doen.xdoel+1; dx++ ) {
|
|
for ( dy=doen.ydoel-1; dy<=doen.ydoel+1; dy++ ) {
|
|
if ( dx>=0 && dy>=0 && dx<maxkolom && dy<maxrij) {
|
|
if ( veld[dx][dy] > 0 ) veld[dx][dy] = doen.speler;
|
|
}
|
|
}
|
|
}
|
|
|
|
// voor het effect is het van belang of het gaat om een verplaatsing
|
|
// of een clonering
|
|
// verplaatsingen gaan over afstand 2, clonaties over afstand 1
|
|
// bepaald delta(x) en delta(y)
|
|
dx = doen.xdoel - doen.xbron;
|
|
dy = doen.ydoel - doen.ybron;
|
|
if ( dx < 0 ) dx *= -1;
|
|
if ( dy < 0 ) dy *= -1;
|
|
// bepaal nu de afstand
|
|
if ( dx >= dy ) afstand = dx;
|
|
else afstand = dy;
|
|
// bij verplaatsing oude veld legen
|
|
if ( afstand==2 ) veld[doen.xbron][doen.ybron] = 0;
|
|
}
|
|
|
|
int ataxxbord::telvirussen (int speler) {
|
|
// telt het aantal virussen voor een speler
|
|
|
|
int x,y; // hulpvariabelen voor iteraties door veld
|
|
int aantal=0; // aantal gevonden virussen
|
|
|
|
for (x=0;x<maxkolom;x++) {
|
|
for (y=0;y<maxrij;y++) {
|
|
if ( veld[x][y] == speler ) aantal++;
|
|
}
|
|
}
|
|
return aantal;
|
|
}
|
|
|
|
bool ataxxbord::bestaanmogelijkezetten (int speler) {
|
|
// kijkt of er uberhaupt wel zetten mogelijk zijn voor een speler
|
|
|
|
int x,y; // hulpvariabelen voor iteraties door veld
|
|
int dx,dy; // afstanden over x en y die een zet doet
|
|
int aantal=0; // aantal gevonden mogelijke zetten
|
|
zet test; // testzet (struct)
|
|
|
|
// kijk voor alle virussen van de speler of er mee gezet kan worden
|
|
for (x=0;x<maxkolom;x++) {
|
|
for (y=0;y<maxrij;y++) {
|
|
if ( veld[x][y] == speler ) {
|
|
// kijk of er zetten mogelijk zijn met stap = 1 of stap = 2
|
|
// met behulp van de functie toegestanezet
|
|
test.speler = speler;
|
|
test.xbron = x;
|
|
test.ybron = y;
|
|
for (dx=-2;dx<=2;dx++) {
|
|
for (dy=-2;dy<=2;dy++) {
|
|
test.xdoel = test.xbron + dx;
|
|
test.ydoel = test.ybron + dy;
|
|
if ( toegestanezet(test) ) aantal++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( aantal>0) return true;
|
|
else return false;
|
|
}
|
|
|
|
zet ataxxbord::allezetten (int speler, int maxzet) {
|
|
// doorloopt alle mogelijke zetten, en geeft de laatste zet terug of
|
|
// de de "maxzet"-ste zet (als maxzet==0 dan de laatste zet)
|
|
|
|
int x,y; // hulpvariabelen voor iteraties door veld
|
|
int dx,dy; // afstanden over x en y die een zet doet
|
|
int aantal=0; // aantal gevonden mogelijke zetten
|
|
zet test; // testzet (struct)
|
|
zet mogenlijkezet; // onthoud de beste mogelijke zet (struct)
|
|
|
|
// initialiseren mogenlijkezet; mocht er geen mogenlijke zet
|
|
// gevonden worden, dan wordt toch deze "lege" zet teruggegeven
|
|
// om een compiler warning te voorkomen
|
|
mogenlijkezet.speler = speler;
|
|
mogenlijkezet.xbron = 0;
|
|
mogenlijkezet.ybron = 0;
|
|
mogenlijkezet.xdoel = 0;
|
|
mogenlijkezet.ydoel = 0;
|
|
mogenlijkezet.aantal = 0;
|
|
|
|
// kijk nu voor alle virussen van de speler wat er mogelijk is
|
|
for (x=0;x<maxkolom;x++) {
|
|
for (y=0;y<maxrij;y++) {
|
|
if ( veld[x][y] == speler ) {
|
|
// kijk of er zetten mogelijk zijn met stap = 1 of stap = 2
|
|
// met gebruik van de functie toegestanezet
|
|
test.speler = speler;
|
|
test.xbron = x;
|
|
test.ybron = y;
|
|
for (dx=-2;dx<=2;dx++) {
|
|
for (dy=-2;dy<=2;dy++) {
|
|
test.xdoel = test.xbron + dx;
|
|
test.ydoel = test.ybron + dy;
|
|
if ( toegestanezet(test) ) {
|
|
aantal++;
|
|
mogenlijkezet = test;
|
|
mogenlijkezet.aantal = aantal;
|
|
if ( aantal==maxzet ) return mogenlijkezet;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// als we hier arriveren is er kennelijk geen zet mogelijk, of zijn er
|
|
// minder dan maxzet zetten mogelijk. in dat laatste geval wordt een
|
|
// eerdere mogelijke zet teruggegeven.
|
|
return mogenlijkezet;
|
|
}
|
|
|
|
zet ataxxbord::randomzet (int speler) {
|
|
// alleen aanroepen na een test op
|
|
// bool ataxxbord::bestaanmogelijkezetten (int speler)
|
|
// als schatting gaan we ervanuit dat er meestal
|
|
// wel minstens 6 zetten mogelijk zijn
|
|
int treffer = (int) willekeur(6);
|
|
return allezetten(speler,treffer);
|
|
}
|
|
|
|
zet ataxxbord::strategiezet (int speler) {
|
|
// voer de zet uit die op dit moment de meeste virussen oplevert
|
|
|
|
zet kandidaatzet; // geheugen voor een kandidaat zet
|
|
int vijand; // nummer van vijandige speler
|
|
int i=0; // hulpvariabele voor iteraties
|
|
int x,y; // hulpvariabelen voor iteraties door veld
|
|
int score; // gevonden score voor een kandidaatzet
|
|
int maxscore=0, maxzet=0; // maximale score bij de beste zet(nr)
|
|
int defensie=2; // mate van defensief spelen
|
|
int agressie=1; // mate van agressief spelen
|
|
int ** tijdelijkveld; // kopie van het echte veld (dynamisch)
|
|
|
|
// vijand bepalen
|
|
if (speler==1) vijand = 2;
|
|
else vijand = 1;
|
|
|
|
// dynamische array maken
|
|
tijdelijkveld = new int * [maxkolom];
|
|
for (x=0;x<maxkolom;x++) {
|
|
tijdelijkveld[x] = new int [maxrij];
|
|
}
|
|
|
|
do {
|
|
i++;
|
|
kandidaatzet = allezetten(speler,i);
|
|
// maak kopie echte bord naar tijdelijkveld
|
|
for (x=0;x<maxkolom;x++) {
|
|
for (y=0;y<maxrij;y++) {
|
|
tijdelijkveld[x][y] = veld[x][y];
|
|
}
|
|
}
|
|
// test de zet op het echte bord ...
|
|
doezet (kandidaatzet);
|
|
// ... en bereken een score (agressie is afhankelijk van deze scoreberekening)
|
|
score = defensie * telvirussen(speler) - agressie * telvirussen(vijand);
|
|
if ( score > maxscore ) {
|
|
maxscore = score;
|
|
maxzet = i;
|
|
}
|
|
// herstel het juiste bord
|
|
for (x=0;x<maxkolom;x++) {
|
|
for (y=0;y<maxrij;y++) {
|
|
veld[x][y] = tijdelijkveld[x][y];
|
|
}
|
|
}
|
|
}
|
|
while ( kandidaatzet.aantal == i );
|
|
|
|
// verwijder dynamisch array
|
|
for (x=0;x<maxkolom;x++) {
|
|
delete [] tijdelijkveld[x];
|
|
}
|
|
delete [] tijdelijkveld;
|
|
tijdelijkveld = NULL;
|
|
|
|
// geef de profitabele zet terug
|
|
kandidaatzet = allezetten (speler, maxzet);
|
|
return kandidaatzet;
|
|
}
|
|
|
|
void ataxxbord::omwisselen() {
|
|
int x,y; // hulpvariabelen voor iteraties door veld
|
|
int hulp;
|
|
for (x=0;x<maxkolom;x++) {
|
|
for (y=0;y<maxrij;y++) {
|
|
hulp = veld[x][y];
|
|
if ( hulp == 1 ) veld[x][y] = 2;
|
|
if ( hulp == 2 ) veld[x][y] = 1;
|
|
}
|
|
}
|
|
}
|