Created
December 1, 2010 10:54
-
-
Save Zegnat/723329 to your computer and use it in GitHub Desktop.
Pearls before Swine. For school, I am not a C++ developer and never will be.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <conio+.h> | |
#include <cmath> | |
#include <time.h> | |
using namespace std; | |
// SETTINGS | |
#define MIN_LINES 2 | |
#define MAX_LINES 8 | |
#define MIN_PEARL 1 | |
#define MAX_PEARL 6 | |
#define MISERE TRUE | |
#define MOVE_WAIT TRUE | |
// MANIPULATORS: | |
double chartodouble(char* c) { | |
double n = 0, in = 0; | |
int t; | |
bool dec = false, neg = false; | |
for (int i=strlen(c)-1;i>=0;i--) { | |
if ((t=c[i]-48)<10 && t>-1) { | |
n += t*pow(10,in); | |
in++; | |
neg = false; | |
} else if ((t==-2||t==-4) && !dec && in!=0) { | |
n /= pow(10,in); | |
in = 0; | |
dec = true; | |
neg = false; | |
} else if (t==-3) neg = !neg; | |
} | |
if (neg) n *= -1; | |
return n; | |
} | |
char* toLowerCase(char* c) { | |
for (int i=0;i<(int)strlen(c);i++) c[i] = tolower(c[i]); | |
return c; | |
} | |
int arrsum(int* a) { | |
int s = 0; | |
for (int i=1;i<(a[0]+1);i++) s += a[i]; | |
return s; | |
} | |
// GAME MECHANICS: | |
int *generate_level() { | |
size_t s = rand() % (MAX_LINES+1-MIN_LINES) + MIN_LINES + 1; | |
int *a = new int[s]; | |
a[0] = (int)s-1; | |
for (size_t i=1;i<s;i++) a[i] = rand() % (MAX_PEARL+1-MIN_PEARL) + MIN_PEARL; | |
return a; | |
/* Returning an array from a function: http://www.cplusplus.com/forum/beginner/6644/ */ | |
} | |
void draw_head() { | |
clrscr(); | |
int l = (MAX_PEARL+5)/2-9; | |
if (l<1) l = 1; | |
for (int i=0;i<l;i++) cout << " "; | |
cout << "PEARLS BEFORE SWINE" << endl; | |
l = MAX_PEARL+5; | |
if (l<21) l = 21; | |
for (int i=0;i<l;i++) cout << "*"; | |
cout << endl << endl; | |
} | |
void draw_level(int* level, int hilight=0) { | |
draw_head(); | |
for (int i=1;i<(level[0]+1);i++) { | |
if (i==hilight) cout << ">" << i << ": "; | |
else cout << " " << i << ": "; | |
for (int j=0;j<level[i];j++) { | |
cout << "O"; | |
} | |
cout << endl; | |
} | |
cout << endl; | |
} | |
int *AI(int* a) { | |
int X = 0, chosen_heap, nb_remove, heaps_twomore = 0, heaps_one = 0; | |
for (int i=1;i<(a[0]+1);i++) X = X^a[i]; | |
if (X==0) { | |
/* New: remove random number of pearls from random row. */ | |
int row, before; | |
do { | |
row = rand()%(a[0]+1)+1; | |
before = a[row]; | |
if (a[row]>0) { | |
if (a[row]==1) a[row] = 0; | |
else a[row] = rand()%a[row]; | |
} | |
} while (before<1); | |
/* Original: remove the first row with more than 0 pearls completely. | |
for (int i=1;i<(a[0]+1);i++) { | |
if (a[i]>0) { | |
//a[i] = 0; | |
a[i] = a[i]-1; | |
break; | |
} | |
}*/ | |
} else { | |
for (int i=1;i<(a[0]+1);i++) { | |
if ((a[i]^X)<a[i]) chosen_heap = i; | |
} | |
nb_remove = a[chosen_heap] - (a[chosen_heap]^X); | |
for (int i=1,n;i<(a[0]+1);i++) { | |
if (chosen_heap==i) n = a[i]-nb_remove; | |
else n = a[i]; | |
if (n>1) heaps_twomore += 1; | |
} | |
if (heaps_twomore==0) { | |
for (int i=1;i<(a[0]+1);i++) { | |
if (a[i]>a[chosen_heap]) chosen_heap = i; | |
} | |
for (int i=1;i<(a[0]+1);i++) { | |
if (a[i]==1) heaps_one++; | |
} | |
if (heaps_one%2!=(int)MISERE) nb_remove = a[chosen_heap]-1; | |
else nb_remove = a[chosen_heap]; | |
} | |
a[chosen_heap] = a[chosen_heap] - nb_remove; | |
} | |
return a; | |
/* Ported from Wikipedia's Python implementation: http://en.wikipedia.org/wiki/Nim#Mathematical_theory */ | |
} | |
// PLAY THE GAME: | |
int main() { | |
if ( | |
MIN_LINES<2|| | |
MIN_PEARL<1|| | |
MAX_LINES<MIN_LINES|| | |
MAX_PEARL<MIN_PEARL|| | |
!(MISERE==0||MISERE==1)|| | |
!(MOVE_WAIT==0||MOVE_WAIT==1) | |
) { | |
cout << "The game can not run with the current settings..."; | |
_getch(); | |
return 0; | |
} | |
srand((int)time(0)); | |
bool play = true; | |
do { | |
int* level = generate_level(); | |
char input[50]; | |
int row, qty, last; | |
do { | |
draw_level(level); | |
cout << "Do you want to start? (Y/N)" << endl << "> "; | |
cin >> input; | |
toLowerCase(input); | |
} while ( | |
strcmp("n",input)!=0&& | |
strcmp("no",input)!=0&& | |
strcmp("y",input)!=0&& | |
strcmp("yes",input)!=0 | |
); | |
if (input[0]=='n') level = AI(level); | |
if (arrsum(level)==(int)MISERE) { | |
draw_level(level); | |
cout << "You lost."; | |
} else { | |
do { | |
row = 0, qty = 0; | |
do { | |
draw_level(level); | |
cout << "Pick a row." << endl << "> "; | |
cin >> input; | |
row = (int)chartodouble(input); | |
if (row>level[0]||row<1||level[row]==0) row = 0; | |
} while (row==0); | |
do { | |
draw_level(level,row); | |
cout << "Number of pearls to remove." << endl << "> "; | |
cin >> input; | |
qty = (int)chartodouble(input); | |
if (qty>level[row]||qty<1) qty = 0; | |
} while (qty==0); | |
level[row] = level[row]-qty; | |
last = 0; | |
if (arrsum(level)>1) { | |
if (MOVE_WAIT) { | |
draw_level(level); | |
cout << "Computer wants to move." << endl << "Press any button..."; | |
_getch(); | |
} | |
AI(level); | |
last = 1; | |
} | |
} while (arrsum(level)>1); | |
draw_level(level); | |
cout << "WINNER: "; | |
if (last==(int)MISERE) cout << "COMPUTER!"; | |
else cout << "YOU!"; | |
_getch(); | |
do { | |
draw_head(); | |
cout << "Play again? (Y/N)" << endl << "> "; | |
cin >> input; | |
toLowerCase(input); | |
} while ( | |
strcmp("n",input)!=0&& | |
strcmp("no",input)!=0&& | |
strcmp("y",input)!=0&& | |
strcmp("yes",input)!=0 | |
); | |
if (input[0]=='n') play = false; | |
} | |
} while(play); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment