many fixes
This commit is contained in:
parent
7e3110d1c3
commit
18ad1e286c
616
tak.c
616
tak.c
|
@ -1,4 +1,3 @@
|
|||
// TODO: call tak
|
||||
// TODO: trap ctrl-c
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
|
@ -25,7 +24,7 @@
|
|||
//#define FORMAT_STACK "|[%-10s]|"
|
||||
#define FORMAT_OWNER "| %s%c%c%s "
|
||||
#define FORMAT_STACK "| %-10s "
|
||||
#define FORMAT_AIVAL "| %s%d%s "
|
||||
#define FORMAT_AIVAL "| %s%5d%s /%2d "
|
||||
|
||||
#define LINEPART "--------------"
|
||||
#define TRUE (-1)
|
||||
|
@ -43,8 +42,10 @@
|
|||
|
||||
char board[MAXW*MAXH][MAXBOARDSTRLEN];
|
||||
int aivalue[MAXW*MAXH];
|
||||
#define BLOCKED -12345
|
||||
int aidef[MAXW*MAXH];
|
||||
#define BLOCKED -999
|
||||
char cmdbuf[MAX_CMD_LEN];
|
||||
char aireason[MAXW*MAXH][2048];
|
||||
|
||||
int tilesleft[MAXPLAYERS];
|
||||
int capsleft[MAXPLAYERS];
|
||||
|
@ -56,12 +57,15 @@ int ai[MAXPLAYERS];
|
|||
// for game log
|
||||
char topofmove = ' ';
|
||||
int flattened = FALSE;
|
||||
int tak[MAXPLAYERS];
|
||||
|
||||
char movelog[256];
|
||||
|
||||
|
||||
int debug = FALSE;
|
||||
|
||||
int xmod[]={0, 1, 0, -1}; /// nesw
|
||||
int ymod[]={1, 0, -1, 0}; /// nesw
|
||||
enum direction {NORTH = 0, EAST = 1, SOUTH = 2, WEST = 3};
|
||||
|
||||
int size=5;
|
||||
|
@ -105,10 +109,11 @@ int setupround(void) {
|
|||
capsleft[i] = startcaps;
|
||||
hasroad[i] = FALSE;
|
||||
roundpoints[i] = 0;
|
||||
tak[i] = FALSE;
|
||||
}
|
||||
ai[0] = FALSE;
|
||||
ai[1] = FALSE;
|
||||
//ai[1] = TRUE;
|
||||
//ai[1] = FALSE;
|
||||
ai[1] = TRUE;
|
||||
|
||||
for (i=0; i<MAXPLAYERS; i++) {
|
||||
roundpoints[i] = 0;
|
||||
|
@ -188,6 +193,18 @@ char counttiles(char *stack) {
|
|||
return count;
|
||||
}
|
||||
|
||||
int getownernumxy(int x, int y) {
|
||||
return getpnum(getownerxy(x,y));
|
||||
}
|
||||
|
||||
|
||||
char getownerxy(int x, int y) {
|
||||
char *s;
|
||||
s = board[y*w+x];
|
||||
return getowner(s);
|
||||
}
|
||||
|
||||
|
||||
char getowner(char *stack) {
|
||||
int pos;
|
||||
if (!stack) return ' ';
|
||||
|
@ -263,7 +280,7 @@ char *readcmd(char *cmd) {
|
|||
}
|
||||
printf("%s",BOLD);
|
||||
if (ai[turn]) {
|
||||
genaicmd(cmd, FALSE);
|
||||
genaicmd(cmd, TRUE, (turnnumber == 1) ? TRUE : FALSE);
|
||||
printf("%s\n",cmd);
|
||||
} else {
|
||||
fgets(cmd ,MAX_CMD_LEN, stdin);
|
||||
|
@ -275,7 +292,206 @@ char *readcmd(char *cmd) {
|
|||
return cmd;
|
||||
}
|
||||
|
||||
char *genaicmd(char *cmd, int showdb) {
|
||||
int rowhasmod(int sx, int sy, char mod, int who) {
|
||||
int count=0;
|
||||
int x;
|
||||
if (!isvalidxy(sx,sy)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (x=0; x < w; x++) {
|
||||
if (getmodxy(x,sy) == mod) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
int colhasmod(int sx, int sy, char mod, int who) {
|
||||
int count=0;
|
||||
int y;
|
||||
if (!isvalidxy(sx,sy)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (y=0; y < h; y++) {
|
||||
if (getmodxy(sx,y) == mod) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
int countownedinrow(int sx, int sy, int who) {
|
||||
int count=0;
|
||||
int x;
|
||||
char *s;
|
||||
if (!isvalidxy(sx,sy)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (x=0; x < w; x++) {
|
||||
if (x != sx) {
|
||||
s = board[sy*w+x];
|
||||
if (getpnum(getowner(s)) == who) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
int countownedincol(int sx, int sy, int who) {
|
||||
int count=0;
|
||||
int y;
|
||||
char *s;
|
||||
if (!isvalidxy(sx,sy)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (y=0; y < h; y++) {
|
||||
if (y != sy) {
|
||||
s = board[y*w+sx];
|
||||
if (getpnum(getowner(s)) == who) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
int countadjacent(int x, int y, int who) {
|
||||
int count=0,d;
|
||||
int newx,newy;
|
||||
char *s;
|
||||
if (!isvalidxy(x,y)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (d=0; d <=3; d++) {
|
||||
newx = x + xmod[d];
|
||||
newy = y + ymod[d];
|
||||
//printf("* checking %d,%d for spaces owned by who=%d\n",newx,newy,who);
|
||||
if (isvalidxy(newx,newy)) {
|
||||
//printf("* %d,%d is valid\n",newx,newy);
|
||||
s = board[newy*w+newx];
|
||||
//printf("* %d,%d is owned by: %c (player %d)\n",newx,newy,getowner(s),getpnum(getowner(s)));
|
||||
if (getpnum(getowner(s)) == who) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void aiupdatetile(int x, int y) {
|
||||
int multi;
|
||||
int xpos,ypos;
|
||||
int idx = y*w+x;
|
||||
int n,a,b,c;
|
||||
char temp[1024];
|
||||
|
||||
xytopos(x,y,&xpos,&ypos);
|
||||
|
||||
if (!canplacetile(turn, x, y, ' ', NULL) &&
|
||||
!canmoveanyto(turn, x, y, NULL, TRUE)) {
|
||||
aivalue[idx] = BLOCKED;
|
||||
} else if (xywouldgivewinto(turn, x, y)) { // would make us win
|
||||
modaivalue(x, y, 999, "would make us win");
|
||||
modaivalue_around(x, y, 10, "would make us win"); //adjust surrounding
|
||||
modaidef_around(x, y, 1);
|
||||
modaidef(x, y, -999);
|
||||
} else if (xywouldgivewinto(1-turn, x, y)) { // would make other player win
|
||||
modaivalue(x, y, 800, "would give win to other player");
|
||||
modaivalue_around(x, y, 12, "would give win to other player"); //adjust surrounding
|
||||
modaidef(x, y, 10);
|
||||
modaidef_around(x, y, 2);
|
||||
}
|
||||
|
||||
// if we already own it, probably dont want to go there
|
||||
if (getownernumxy(x, y) == turn) {
|
||||
modaivalue(x,y, -15, "we own this space already");
|
||||
} else {
|
||||
n = countadjacent(x,y,turn);
|
||||
// modify based on adjacent controlled locations
|
||||
snprintf(temp, 1024, "we own %d adjacent cells", n);
|
||||
modaivalue(x,y, n * 1, temp); // controlled by us
|
||||
}
|
||||
|
||||
if (getownernumxy(x, y) == turn) {
|
||||
multi = 1;
|
||||
} else {
|
||||
multi = 2;
|
||||
}
|
||||
n = countadjacent(x,y,1 - turn);
|
||||
snprintf(temp, 1024, "other player owns %d adjacent cells", n);
|
||||
modaivalue(x,y, n * multi, temp); // controlled by other player
|
||||
modaidef_around(x, y, countadjacent(x,y,1 - turn) * 1);
|
||||
|
||||
// If we DONT own this location, consider other stones in the same row/col
|
||||
if (getownernumxy(x, y) != turn) {
|
||||
n = countownedinrow(x,y,turn) - rowhasmod(x,y,turn,'|'); // dont include our walls since they don't count in roads
|
||||
snprintf(temp, 1024, "we own %d cells in this row", n);
|
||||
modaivalue(x,y, n * 6, temp);
|
||||
|
||||
n = countownedincol(x,y,turn) - colhasmod(x,y,turn,'|'); // don't include our walls since they don't count in roads
|
||||
snprintf(temp, 1024, "we own %d cells in this column", n);
|
||||
modaivalue(x,y, n * 6, temp);
|
||||
|
||||
// opponent tiles in row, offset by our walls/caps
|
||||
multi = 2;
|
||||
a = rowhasmod(x,y,'^',turn);
|
||||
multi -= a;
|
||||
b = rowhasmod(x,y,'|',turn);
|
||||
multi -= b;
|
||||
if (getownernumxy(x, y) == ' ') { // cells noone owns are more valuable
|
||||
c = 1;
|
||||
multi += 1;
|
||||
} else {
|
||||
c=0;
|
||||
}
|
||||
n = countownedinrow(x,y,1-turn) - rowhasmod(x,y,'|',1 - turn); // don't include their walls
|
||||
snprintf(temp, 1024, "other player has %d cells in row (we have %d caps + %d walls == %d multiplier)", n, a, b, multi);
|
||||
if (multi > 0) {
|
||||
modaivalue(x,y, n * multi, temp);
|
||||
}
|
||||
modaidef(x,y, n * 1);
|
||||
|
||||
// opponent tiles in col, offset by our walls/caps
|
||||
multi = 2;
|
||||
a = colhasmod(x,y,'^',turn);
|
||||
multi -= a;
|
||||
b = colhasmod(x,y,'|',turn);
|
||||
multi -= b;
|
||||
|
||||
if (getownernumxy(x, y) == ' ') { // cells noone owns are more valuable
|
||||
c = 1;
|
||||
multi += 1;
|
||||
} else {
|
||||
c=0;
|
||||
}
|
||||
n = countownedincol(x,y,1-turn) - colhasmod(x,y,'|',1 - turn); // don't include their walls
|
||||
snprintf(temp, 1024, "other player has %d cells in col (empty=%d, we have %d caps + %d walls == %d multiplier)", n, c, a, b, multi);
|
||||
if (multi > 0) {
|
||||
modaivalue(x,y, n * multi, temp);
|
||||
}
|
||||
modaidef(x,y, n * 1);
|
||||
}
|
||||
|
||||
|
||||
// reduce defence required for each or our caps in this row/col
|
||||
a = colhasmod(x,y,'^',turn);
|
||||
b = rowhasmod(x,y,'^',turn);
|
||||
modaidef(x,y, (a+b) * -1);
|
||||
a = colhasmod(x,y,'|',turn);
|
||||
b = rowhasmod(x,y,'|',turn);
|
||||
modaidef(x,y, (a+b) * -1);
|
||||
}
|
||||
|
||||
char *genaicmd(char *cmd, int showdb, int useworst) {
|
||||
int x,y,best;
|
||||
int ncandidates;
|
||||
int candidate[MAXW*MAXH];
|
||||
|
@ -284,28 +500,29 @@ char *genaicmd(char *cmd, int showdb) {
|
|||
for (y=0; y < h; y++) {
|
||||
for (x=0; x < w; x++) {
|
||||
aivalue[y*w+x] = 500;
|
||||
aidef[y*w+x] = 0;
|
||||
strcpy(aireason[y*w+x], "");
|
||||
}
|
||||
}
|
||||
// mark anywhere we definitely cannot go
|
||||
for (y=0; y < h; y++) {
|
||||
for (x=0; x < w; x++) {
|
||||
int idx = y*w+x;
|
||||
if (!canplacetile(turn, x, y, ' ', NULL) &&
|
||||
!canmoveanyto(turn, x, y, NULL)) {
|
||||
aivalue[idx] = BLOCKED;
|
||||
} else if (xywouldgivewinto(1-turn, x, y)) {
|
||||
modaivalue(x, y, 999);
|
||||
}
|
||||
aiupdatetile(x,y);
|
||||
}
|
||||
}
|
||||
|
||||
// determine the best priority
|
||||
best = -1;
|
||||
if (useworst) best=99999;
|
||||
else best = -1;
|
||||
|
||||
for (y=0; y < h; y++) {
|
||||
for (x=0; x < w; x++) {
|
||||
if ((aivalue[y*w+x] != BLOCKED) &&
|
||||
(aivalue[y*w+x] > best)) {
|
||||
best = aivalue[y*w+x];
|
||||
if (aivalue[y*w+x] != BLOCKED) {
|
||||
if (useworst) {
|
||||
if (aivalue[y*w+x] < best) best = aivalue[y*w+x];
|
||||
} else {
|
||||
if (aivalue[y*w+x] > best) best = aivalue[y*w+x];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -315,7 +532,7 @@ char *genaicmd(char *cmd, int showdb) {
|
|||
showaivalues(best);
|
||||
}
|
||||
|
||||
printf("*** best value is = %d\n", best);
|
||||
//printf("*** best value is = %d\n", best);
|
||||
// pick randomly from the best priority
|
||||
ncandidates = 0;
|
||||
for (y=0; y < h; y++) {
|
||||
|
@ -326,8 +543,7 @@ printf("*** best value is = %d\n", best);
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
printf("*** ncandidates = %d\n", ncandidates);
|
||||
//printf("*** ncandidates = %d\n", ncandidates);
|
||||
|
||||
if (ncandidates == 0) {
|
||||
sprintf(cmd, "\\r");
|
||||
|
@ -339,17 +555,40 @@ printf("*** ncandidates = %d\n", ncandidates);
|
|||
xytopos(xsel,ysel,&xpossel, &ypossel);
|
||||
|
||||
// we place a tile here or move here?
|
||||
if (canmoveanyto(turn, x, y, str)) {
|
||||
if (canplacetile(turn, xsel, ysel, ' ', NULL)) {
|
||||
char mod = ' ';
|
||||
int chance = aidef[ysel*w+xsel]*15;
|
||||
// wall or cap?
|
||||
if (pctchance(chance)) {
|
||||
if ((capsleft[turn] > 0) &&
|
||||
pctchance(chance) &&
|
||||
canplacetile(turn, xsel, ysel, '^', NULL)) {
|
||||
mod = '^';
|
||||
} else if (canplacetile(turn, xsel, ysel, '|', NULL)) {
|
||||
mod = '|';
|
||||
}
|
||||
}
|
||||
// place
|
||||
if (mod == ' ') {
|
||||
sprintf(cmd, "%c%c", xpossel,ypossel);
|
||||
} else {
|
||||
sprintf(cmd, "%c%c%c", mod,xpossel,ypossel);
|
||||
}
|
||||
} else if (canmoveanyto(turn, xsel, ysel, str, TRUE)) {
|
||||
// move
|
||||
sprintf(cmd, "%s", str);
|
||||
} else {
|
||||
// place
|
||||
sprintf(cmd, "%c%c", xpossel,ypossel);
|
||||
}
|
||||
}
|
||||
return cmd;
|
||||
}
|
||||
|
||||
int pctchance(int num) {
|
||||
if (rand() % 100 < num) {
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int xywouldgivewinto(int who, int tx, int ty) {
|
||||
char board2[MAXW*MAXH][MAXBOARDSTRLEN];
|
||||
int x,y,wouldwin = FALSE;
|
||||
|
@ -373,12 +612,62 @@ void idxtoxy(int idx, int *x, int *y) {
|
|||
if (y) *y = idx / w;
|
||||
}
|
||||
|
||||
int modaivalue(int x,int y,int amt) {
|
||||
int modaidef(int x,int y,int amt) {
|
||||
int idx=y*w+x;
|
||||
if (!isvalidxy(x,y)) {
|
||||
return TRUE;
|
||||
}
|
||||
aidef[idx] += amt;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
int modaivalue(int x,int y,int amt, char *reason) {
|
||||
char temp[512];
|
||||
int idx=y*w+x;
|
||||
if (!isvalidxy(x,y)) {
|
||||
return TRUE;
|
||||
}
|
||||
if (aivalue[idx] == BLOCKED) {
|
||||
return TRUE;
|
||||
}
|
||||
aivalue[idx] += amt;
|
||||
snprintf(temp, 512, " [%s%-3d] %s\n", (amt > 0) ? "+" : "", amt, reason ? reason : "<unspecified>");
|
||||
strcat(aireason[idx], temp);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int modaivalue_around(int x,int y,int amt, char *reason) {
|
||||
int newx,newy,d;
|
||||
int xpos,ypos;
|
||||
char localreason[1024];
|
||||
if (!isvalidxy(x,y)) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
xytopos(x,y,&xpos,&ypos);
|
||||
|
||||
snprintf(localreason, 1024, "(from adjacent tile %c%c): %s", xpos,ypos, reason);
|
||||
for (d=0; d <=3; d++) {
|
||||
newx = x + xmod[d];
|
||||
newy = y + ymod[d];
|
||||
modaivalue(newx, newy, amt, localreason);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
int modaidef_around(int x,int y,int amt) {
|
||||
int newx,newy,d;
|
||||
if (!isvalidxy(x,y)) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
for (d=0; d <=3; d++) {
|
||||
newx = x + xmod[d];
|
||||
newy = y + ymod[d];
|
||||
modaidef(newx, newy, amt);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -421,9 +710,24 @@ int checkendgame(void) {
|
|||
if (isboardfull()) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void checkfortak(int who) {
|
||||
int x,y;
|
||||
// check for 'tak' condition
|
||||
tak[who] = FALSE;
|
||||
for (y=0; y < h; y++) {
|
||||
for (x=0; x < w; x++) {
|
||||
if (xywouldgivewinto(who, x, y)) {
|
||||
tak[who] = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int getstartcapstones(int sz) {
|
||||
switch (sz) {
|
||||
case 3:
|
||||
|
@ -468,6 +772,8 @@ int nextturn(void) {
|
|||
// reset game log variables?
|
||||
topofmove = ' ';
|
||||
flattened = FALSE;
|
||||
tak[0] = FALSE;
|
||||
tak[1] = FALSE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -535,7 +841,7 @@ int movetile(int count,char xch,char ych, char dir, char *dropstr) {
|
|||
char dropping[MAXSTACK*2];
|
||||
char *bpos,*newbpos,*p,*dp,*mp;
|
||||
int pass;
|
||||
int xmod,ymod;
|
||||
int xmodamt,ymodamt;
|
||||
int numtomove;
|
||||
char err[256];
|
||||
postoxy(xch,ych,&x, &y);
|
||||
|
@ -577,7 +883,7 @@ int movetile(int count,char xch,char ych, char dir, char *dropstr) {
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
dirtoxy(dir,&xmod,&ymod);
|
||||
dirtoxy(dir,&xmodamt,&ymodamt);
|
||||
numtomove = count;
|
||||
|
||||
// First pass: validate each step
|
||||
|
@ -616,8 +922,8 @@ int movetile(int count,char xch,char ych, char dir, char *dropstr) {
|
|||
//printf("remaining in mp: %d\n",remaining);;
|
||||
//printf("move %s from %d,%d (%c%c)", getdirname(dir), x,y,newxch,newych);
|
||||
|
||||
x += xmod;
|
||||
y += ymod;
|
||||
x += xmodamt;
|
||||
y += ymodamt;
|
||||
// still on the board?
|
||||
if (!isvalidxy(x,y)) {
|
||||
printf("* %s can't move %s tiles %s from %c%c - would move off board with %d tiles remaining\n",getpname(turn),countstr,getdirname(dir), xch,ych, remaining);
|
||||
|
@ -777,7 +1083,8 @@ int canplacetile(int who, int x, int y, int mod, char *why) {
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
int canmoveanyto(int who, int tx, int ty, char *why) {
|
||||
|
||||
int canmoveanyto(int who, int tx, int ty, char *why, int safe) {
|
||||
int x,y;
|
||||
if (!canmoveto(who, tx, ty, why)) return FALSE;
|
||||
if (why) strcpy(why,"");
|
||||
|
@ -793,8 +1100,16 @@ int canmoveanyto(int who, int tx, int ty, char *why) {
|
|||
if (ok && (x != tx) && (y != ty)) { // same row/col
|
||||
ok = FALSE;
|
||||
}
|
||||
if ( ok && !canmovefrom(who, x, y, why)) { // got somethong to move here
|
||||
ok = FALSE;
|
||||
if (ok) {
|
||||
if (safe) {
|
||||
if (!canmovefrom(who, x, y, why)) { // got somethong to move here
|
||||
ok = FALSE;
|
||||
}
|
||||
} else {
|
||||
if (!willmovefrom(who, x, y, why)) { // got somethong which is safe to move here
|
||||
ok = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
count = counttiles(board[y*w+x]);
|
||||
if (ok && (x == tx) && abs(tx - x) > count) { // distance ok?
|
||||
|
@ -804,7 +1119,7 @@ int canmoveanyto(int who, int tx, int ty, char *why) {
|
|||
ok = FALSE;
|
||||
}
|
||||
// can this stack get one of our color to there???
|
||||
if (canmakedropstr(who, x,y,tx,ty,why)) {
|
||||
if (ok && canmakedropstr(who, x,y,tx,ty,why)) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
@ -819,8 +1134,6 @@ int canmakedropstr(int who, int sx, int sy, int dx, int dy, char *str) { // retu
|
|||
char *p;
|
||||
char *spos;
|
||||
int smod;
|
||||
int xmod[]={0, 1, 0, -1}; /// nesw
|
||||
int ymod[]={1, 0, -1, 0}; /// nesw
|
||||
char localstr[256];
|
||||
int db = TRUE;
|
||||
|
||||
|
@ -880,12 +1193,14 @@ int canmakedropstr(int who, int sx, int sy, int dx, int dy, char *str) { // retu
|
|||
strcat(localstr, temp);
|
||||
if (str) strcpy(str,localstr);
|
||||
return TRUE;
|
||||
// TODO: go further to control mlre locations
|
||||
// TODO: go further to control more locations
|
||||
} else {
|
||||
char *z;
|
||||
// not there yet.
|
||||
|
||||
// must drop at least one
|
||||
// TODO: figure out how many we can drop and
|
||||
// still reach dst
|
||||
// TODO: drop more than 1, prefer our color
|
||||
//z = strchr(mp, getpchar(who));
|
||||
|
||||
|
@ -894,16 +1209,32 @@ int canmakedropstr(int who, int sx, int sy, int dx, int dy, char *str) { // retu
|
|||
if (z) {
|
||||
// if match, drop so it's on top
|
||||
int numtodrop = (z - moving) + 1;
|
||||
char temp[10];
|
||||
sprintf(temp, "%1d",numtodrop);
|
||||
strcat(localstr, temp);
|
||||
int didsomething = TRUE;
|
||||
char temp[10],owner;
|
||||
// would dropping this amt let the
|
||||
// other player win?
|
||||
while (didsomething) {
|
||||
didsomething = FALSE;
|
||||
owner = *(z+numtodrop-1);
|
||||
if (getpnum(owner) == 1-who) {
|
||||
if (xywouldgivewinto(1-who, x, y)) {
|
||||
if (++numtodrop >= counttiles(mp)) {
|
||||
break;
|
||||
}
|
||||
didsomething = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (db) printf("db: ** numtodrop: %d. tiles in stack: %d (%s)\n", numtodrop, counttiles(mp), mp);
|
||||
// no more tiles in moving stack??
|
||||
if (numtodrop >= counttiles(mp)) {
|
||||
// this stack size.
|
||||
stillgood = FALSE;
|
||||
} else {
|
||||
sprintf(temp, "%1d",numtodrop);
|
||||
strcat(localstr, temp);
|
||||
if (db) printf("db: ** numtodrop: %d. tiles in stack: %d (%s)\n", numtodrop, counttiles(mp), mp);
|
||||
|
||||
// remove dropped tiles from moving stack
|
||||
mp += numtodrop;
|
||||
if (db) printf("db: ** new tiles in stack: %d (%s)\n", counttiles(mp), mp);
|
||||
|
@ -933,6 +1264,17 @@ char getdirchar(int dir) {
|
|||
return '=';
|
||||
}
|
||||
|
||||
int willmovefrom(int who, int x, int y, char *why) {
|
||||
// would moving away from here make the other player win?
|
||||
|
||||
if (xywouldgivewinto(who, x, y)) {
|
||||
if (why) sprintf(why, "Moving away would open up a win to other player");
|
||||
return FALSE;
|
||||
}
|
||||
return canmovefrom(who, x, y, why);
|
||||
}
|
||||
|
||||
|
||||
int canmovefrom(int who, int x, int y, char *why) {
|
||||
int mod;
|
||||
int idx,xch,ych;
|
||||
|
@ -943,14 +1285,18 @@ int canmovefrom(int who, int x, int y, char *why) {
|
|||
mod = getmod(bpos);
|
||||
|
||||
if (why) strcpy(why,"");
|
||||
if (turnnumber == 1) {
|
||||
if (why) sprintf(why, "cant move on first setup turn.\n");
|
||||
return FALSE;
|
||||
}
|
||||
// is there anything at the source location?
|
||||
if (!strlen(bpos) ) {
|
||||
sprintf(why, "empty source location\n");
|
||||
if (why) sprintf(why, "empty source location\n");
|
||||
return FALSE;
|
||||
}
|
||||
// does the other player own the source location?
|
||||
if (getowner(bpos) == getpchar(1 - who)) {
|
||||
sprintf(why, "not owner of source location\n");
|
||||
if (why) sprintf(why, "not owner of source location\n");
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
|
@ -966,9 +1312,13 @@ int canmoveto(int who, int x, int y, char *why) {
|
|||
mod = getmod(bpos);
|
||||
|
||||
if (why) strcpy(why,"");
|
||||
if (turnnumber == 1) {
|
||||
if (why) sprintf(why, "cant move on first setup turn.\n");
|
||||
return FALSE;
|
||||
}
|
||||
if (mod == '^') {
|
||||
// capstone?
|
||||
sprintf(why, "%s capstone at %c%c\n",getpname(getowner(bpos)), xch,ych);
|
||||
if (why) sprintf(why, "%s capstone at %c%c\n",getpname(getowner(bpos)), xch,ych);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
|
@ -1003,7 +1353,7 @@ int parsecmd(char *cmd) {
|
|||
winner = 1-turn;
|
||||
logmove(turn, cmd, ' ');
|
||||
return FALSE;
|
||||
} else if (strstr(cmd, "\\w ")) { // check if loc would give us a win
|
||||
} else if (strstr(cmd, "\\W ")) { // check if loc would give us a win
|
||||
int xpos,ypos,x,y,wouldwin;
|
||||
p = cmd + 3;
|
||||
xpos = p[0];
|
||||
|
@ -1013,6 +1363,21 @@ int parsecmd(char *cmd) {
|
|||
printf(" *** would %c%c give us a win? %s\n", xpos,ypos,
|
||||
wouldwin ? "YES" : "no");
|
||||
return TRUE;
|
||||
} else if (!strcmp(cmd, "\\b")) {
|
||||
showboard();
|
||||
return TRUE;
|
||||
} else if (strstr(cmd, "\\w ")) {
|
||||
int xpos,ypos,x,y;
|
||||
p = cmd + 3;
|
||||
xpos = p[0];
|
||||
ypos = p[1];
|
||||
postoxy(xpos,ypos,&x,&y);
|
||||
printf("%sAI thoughts for %s%c%c%s%s: [%s%d%s%s]\n",YELLOW,BOLD,xpos,ypos,reset,YELLOW, BOLD,aivalue[y*w+x],reset,YELLOW);
|
||||
printf("%s%s\n",aireason[y*w+x],reset);
|
||||
return TRUE;
|
||||
} else if (!strcmp(cmd, "\\s")) {
|
||||
showscores("Current");
|
||||
return TRUE;
|
||||
} else if (strstr(cmd, "\\m ")) { // check if we can move to loc
|
||||
char temp[256];
|
||||
int xpos,ypos,x,y;
|
||||
|
@ -1020,16 +1385,30 @@ int parsecmd(char *cmd) {
|
|||
xpos = p[0];
|
||||
ypos = p[1];
|
||||
postoxy(xpos,ypos,&x,&y);
|
||||
if (canmoveanyto(turn, x, y, temp)) {
|
||||
if (canmoveanyto(turn, x, y, temp, FALSE)) {
|
||||
printf(" *** %c%c is reachable: %s\n", xpos,ypos, temp);
|
||||
} else {
|
||||
printf(" *** can't move to %c%c\n", xpos,ypos);
|
||||
}
|
||||
return TRUE;
|
||||
} else if (strstr(cmd, "\\c ")) { // count adjacent tiles to loc
|
||||
int xpos,ypos,x,y,num,i;
|
||||
p = cmd + 3;
|
||||
xpos = p[0];
|
||||
ypos = p[1];
|
||||
postoxy(xpos,ypos,&x,&y);
|
||||
for (i = 0; i <= 1; i++) {
|
||||
num = countadjacent(x,y,i);
|
||||
printf("%c%c has %d adjacent %s%s%s controlled locations.\n",xpos,ypos,num,getpcol(i),getpname(i),reset);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
} else if (!strcmp(cmd, "\\a")) { // simlulate AI move for us, with debug info
|
||||
char cmd[256];
|
||||
|
||||
genaicmd(cmd, TRUE);
|
||||
genaicmd(cmd, TRUE, FALSE);
|
||||
printf("%sAI suggested move for %s%s%s%s: %s%s%s%s\n", YELLOW, getpcol(turn),getpname(turn),reset,YELLOW,getpcol(turn), BOLD, cmd, reset);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -1081,6 +1460,7 @@ int parsecmd(char *cmd) {
|
|||
}
|
||||
|
||||
if (!err) {
|
||||
checkfortak(turn);
|
||||
logmove(turn, cmd, topofmove);
|
||||
}
|
||||
|
||||
|
@ -1106,6 +1486,7 @@ void showaivalues(int best) {
|
|||
int x,y;
|
||||
char ch;
|
||||
|
||||
printf("\n");
|
||||
printf(FORMAT_ROWHEAD, ' ');
|
||||
ch = 'a';
|
||||
for (x=0; x < w; x++) {
|
||||
|
@ -1120,8 +1501,16 @@ void showaivalues(int best) {
|
|||
printf(FORMAT_ROWHEAD, ch);
|
||||
for (x=0; x < w; x++) {
|
||||
int val = aivalue[y*w+x];
|
||||
// show owner
|
||||
printf(FORMAT_AIVAL, val == best ? GREEN : YELLOW, val, reset);
|
||||
int def = aidef[y*w+x];
|
||||
char *col;
|
||||
if (val == best) {
|
||||
col = GREEN;
|
||||
} else if (val == BLOCKED) {
|
||||
col = RED;
|
||||
} else {
|
||||
col = YELLOW;
|
||||
}
|
||||
printf(FORMAT_AIVAL, col, val, reset, def);
|
||||
}
|
||||
printf(FORMAT_ROWTAIL, ch);
|
||||
printf("\n");
|
||||
|
@ -1305,6 +1694,13 @@ void showboardbinary(int pnum) {
|
|||
|
||||
}
|
||||
|
||||
void roadlog(char *dname, int dir, int xch, int ych, int newx,int newy) {
|
||||
int newxch,newych;
|
||||
xytopos(newx, newy, &newxch, &newych);
|
||||
fprintf(stderr,"** db: Checking %s (dir %d xm=%d,ym=%d) from %c%c (%c%c == %d,%d)\n", dname, dir, xmod[dir],ymod[dir],xch,ych,newxch,newych,newx,newy);
|
||||
}
|
||||
|
||||
|
||||
int xyvalidforroad(char (*b)[MAXBOARDSTRLEN], int who, int x, int y) {
|
||||
char *cell;
|
||||
cell = b[y*w+x];
|
||||
|
@ -1316,8 +1712,6 @@ int xyvalidforroad(char (*b)[MAXBOARDSTRLEN], int who, int x, int y) {
|
|||
|
||||
|
||||
int checkxyforroad(char (*b)[MAXBOARDSTRLEN], int who, int sx, int sy, int sd) {
|
||||
int xmod[]={0, 1, 0, -1}; /// nesw
|
||||
int ymod[]={1, 0, -1, 0}; /// nesw
|
||||
int x,y,newx,newy,d,xch,ych,newxch,newych;
|
||||
int startxch,startych;
|
||||
int startdir,done,turncount;
|
||||
|
@ -1342,6 +1736,12 @@ int checkxyforroad(char (*b)[MAXBOARDSTRLEN], int who, int sx, int sy, int sd) {
|
|||
|
||||
if (db) fprintf(stderr,"** db: looking for %s roads from %c%c (owned by %c / %d)\n", getpname(who), xch,ych, getowner(b[sy*w+sx]), getpnum(getowner(b[sy*w+sx])));
|
||||
|
||||
// check initial cell
|
||||
if (!xyvalidforroad(b, who,x,y)) {
|
||||
if (db) fprintf(stderr,"** db: %c%c not valid for road - stopping\n", xch,ych);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (getpnum(getowner(b[sy*w+sx])) != who) {
|
||||
if (db) fprintf(stderr,"** db: %s doesn't own %c%c - stopping\n", getpname(who), xch,ych);
|
||||
return FALSE;
|
||||
|
@ -1356,56 +1756,59 @@ int checkxyforroad(char (*b)[MAXBOARDSTRLEN], int who, int sx, int sy, int sd) {
|
|||
leftdir = (d - 1); if (leftdir < 0) leftdir = 3;
|
||||
rightdir = (d + 1); if (rightdir >= 4) rightdir = 0;
|
||||
|
||||
// is there a valid cell in the current dir?
|
||||
newx = x + xmod[d];
|
||||
newy = y + ymod[d];
|
||||
xytopos(newx, newy, &newxch, &newych);
|
||||
// is there a valid cell to the left?
|
||||
newx = x + xmod[leftdir];
|
||||
newy = y + ymod[leftdir];
|
||||
if (db) roadlog("left", leftdir, xch,ych,newx,newy);
|
||||
|
||||
if (db) fprintf(stderr,"** db: Checking forward (dir %d) from %c%c (%c%c)\n", d, xch,ych,newxch,newych);
|
||||
if (xyvalidforroad(b, who,newx,newy)) {
|
||||
x = newx;
|
||||
y = newy;
|
||||
d = leftdir;
|
||||
moved = TRUE;
|
||||
} else { // turn left
|
||||
newx = x + xmod[leftdir];
|
||||
newy = y + ymod[leftdir];
|
||||
}
|
||||
if (!moved) { // forward?
|
||||
newx = x + xmod[d];
|
||||
newy = y + ymod[d];
|
||||
|
||||
xytopos(newx, newy, &newxch, &newych);
|
||||
|
||||
if (db) fprintf(stderr,"** db: Checking left (dir %d) from %c%c (%c%c)\n", leftdir, xch,ych,newxch,newych);
|
||||
if (db) roadlog("forward", d, xch,ych,newx,newy);
|
||||
if (xyvalidforroad(b, who,newx,newy)) {
|
||||
x = newx;
|
||||
y = newy;
|
||||
d = leftdir;
|
||||
moved = TRUE;
|
||||
} else { // turn right
|
||||
newx = x + xmod[rightdir];
|
||||
newy = y + ymod[rightdir];
|
||||
xytopos(newx, newy, &newxch, &newych);
|
||||
if (db) fprintf(stderr,"** db: Checking right (dir %d) from %c%c (%c%c)\n", rightdir, xch,ych,newxch,newych);
|
||||
if (xyvalidforroad(b, who,newx,newy)) {
|
||||
x = newx;
|
||||
y = newy;
|
||||
d = rightdir;
|
||||
moved = TRUE;
|
||||
} else {
|
||||
// reverse direction
|
||||
if (--d < 0) d = 3;
|
||||
if (--d < 0) d = 3;
|
||||
|
||||
if (db) fprintf(stderr,"** db: Turning around (dir %d) from %c%c (%c%c)\n", d, xch,ych,newxch,newych);
|
||||
if (xyvalidforroad(b, who,newx,newy)) {
|
||||
x = newx;
|
||||
y = newy;
|
||||
moved = TRUE;
|
||||
} else {
|
||||
if (db) fprintf(stderr,"** db: Couldn't turn around - no roads.\n");
|
||||
done = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!moved) { // right
|
||||
newx = x + xmod[rightdir];
|
||||
newy = y + ymod[rightdir];
|
||||
if (db) roadlog("right", rightdir, xch,ych,newx,newy);
|
||||
if (xyvalidforroad(b, who,newx,newy)) {
|
||||
x = newx;
|
||||
y = newy;
|
||||
d = rightdir;
|
||||
moved = TRUE;
|
||||
}
|
||||
}
|
||||
if (!moved) { // reverse direction
|
||||
if (--d < 0) d = 3;
|
||||
if (--d < 0) d = 3;
|
||||
newx = x + xmod[d];
|
||||
newy = y + ymod[d];
|
||||
|
||||
if (db) roadlog("backward", d, xch,ych,newx,newy);
|
||||
if (xyvalidforroad(b, who,newx,newy)) {
|
||||
x = newx;
|
||||
y = newy;
|
||||
moved = TRUE;
|
||||
}
|
||||
}
|
||||
if (!moved) {
|
||||
if (db) fprintf(stderr,"** db: Couldn't turn around - no roads.\n");
|
||||
}
|
||||
|
||||
|
||||
if (moved) {
|
||||
xytopos(x, y, &newxch, &newych);
|
||||
if (db) fprintf(stderr,"** db: %c%c is owned by us, moving there.\n", newxch,newych);
|
||||
xch = newxch;
|
||||
ych = newych;
|
||||
|
@ -1483,6 +1886,32 @@ int gotwinner(void) {
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
void determinefinalwinner(void) {
|
||||
if (gamepoints[0] > gamepoints[1]) {
|
||||
winner = 0;
|
||||
} else if (gamepoints[1] > gamepoints[0]) {
|
||||
winner = 1;
|
||||
} else {
|
||||
winner = -1;
|
||||
}
|
||||
|
||||
if (winner == -1) {
|
||||
} else {
|
||||
printf("%s** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **%s\n", getpcol(winner), reset);
|
||||
printf("%s ***** %s%s%s is the victor! %s*****%s\n",
|
||||
getpcol(winner), BOLD,getpname(winner), reset,
|
||||
getpcol(winner), reset);
|
||||
printf("%s** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **%s\n", getpcol(winner), reset);
|
||||
}
|
||||
|
||||
// show totals
|
||||
showscores("Final");
|
||||
// TODO: bold this
|
||||
printf("\n%s--- Press ENTER to end ---%s\n", BOLD, reset);
|
||||
// wait for key
|
||||
fgets(cmdbuf ,MAX_CMD_LEN, stdin);
|
||||
}
|
||||
|
||||
void determinewinner(void) {
|
||||
int x,y,i;
|
||||
int flatstones[MAXPLAYERS];
|
||||
|
@ -1539,17 +1968,17 @@ void determinewinner(void) {
|
|||
}
|
||||
|
||||
// show totals
|
||||
showscores();
|
||||
showscores("Current");
|
||||
// TODO: bold this
|
||||
printf("\n%s--- Press ENTER for next round ---%s\n", BOLD, reset);
|
||||
// wait for key
|
||||
fgets(cmdbuf ,MAX_CMD_LEN, stdin);
|
||||
}
|
||||
|
||||
void showscores(void) {
|
||||
void showscores(char *str) {
|
||||
int i;
|
||||
char temp[64];
|
||||
printf("Current scores:\n");
|
||||
printf("%s scores:\n", str);
|
||||
for (i=0; i<MAXPLAYERS; i++) {
|
||||
sprintf(temp, "%s%12s%s",getpcol(i), getpname(i), reset);
|
||||
printf(" %s: %s%d points%s\n", temp, getpcol(i),gamepoints[i], reset);
|
||||
|
@ -1592,10 +2021,14 @@ void logmove(int who, char *txt, char append) {
|
|||
if (flattened) {
|
||||
strcat(temp, "*");
|
||||
}
|
||||
if (tak[who]) {
|
||||
strcat(temp, "'");
|
||||
}
|
||||
|
||||
// first player's turn?
|
||||
if (who == firstturn) {
|
||||
sprintf(movelog, "%s", temp);
|
||||
printf("%s%s%d.%s%s %s ...%s\n", YELLOW, BOLD, turnnumber, reset, YELLOW, movelog,reset);
|
||||
} else {
|
||||
strcat(movelog, " ");
|
||||
strcat(movelog, temp);
|
||||
|
@ -1626,4 +2059,5 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
nextround();
|
||||
}
|
||||
determinefinalwinner();
|
||||
}
|
||||
|
|
24
tak.h
24
tak.h
|
@ -35,22 +35,38 @@ void printbinaryline(char prefix, int num, int wantcr);
|
|||
int playerhasroads(int pnum, char (*b)[]);
|
||||
void updateroadstatus(void);
|
||||
char *makecolorstr(char *orig, char *newstr);
|
||||
void showscores(void);
|
||||
void showscores(char *str);
|
||||
int checkxyforroad(char (*b)[], int who, int sx, int sy, int sd);
|
||||
void pickfirstplayer(void);
|
||||
int xyvalidforroad(char (*b)[], int who, int x, int y);
|
||||
void logmove(int who, char *txt, char append);
|
||||
int normalise(char *a);
|
||||
char *genaicmd(char *cmd, int showdb);
|
||||
char *genaicmd(char *cmd, int showdb, int useworst);
|
||||
int canplacetile(int who, int x, int y, int mod, char *why);
|
||||
int canmoveto(int who, int x, int y, char *why);
|
||||
void idxtoxy(int idx, int *x, int *y);
|
||||
void xytopos(int x, int y, int *xch, int *ych);
|
||||
int gotwinner(void);
|
||||
int xywouldgivewinto(int who, int tx, int ty);
|
||||
int modaivalue(int x,int y,int amt);
|
||||
int modaivalue(int x,int y,int amt, char *reason);
|
||||
int modaivalue_around(int x,int y,int amt, char *reason);
|
||||
int modaidef(int x,int y,int amt);
|
||||
int modaidef_around(int x,int y,int amt);
|
||||
int canmovefrom(int who, int x, int y, char *why);
|
||||
int canmoveanyto(int who, int x, int y, char *why);
|
||||
int willmovefrom(int who, int x, int y, char *why);
|
||||
int canmoveanyto(int who, int x, int y, char *why, int safe);
|
||||
int canmakedropstr(int who, int sx, int sy, int dx, int dy, char *str);
|
||||
char getdirchar(int dir);
|
||||
void showaivalues(int best);
|
||||
int countadjacent(int x, int y, int who);
|
||||
int getpnum(int n);
|
||||
int countownedinrow(int sx, int sy, int who);
|
||||
int countownedincol(int sx, int sy, int who);
|
||||
int pctchance(int num);
|
||||
int colhasmod(int sx, int sy, char mod, int who);
|
||||
int rowhasmod(int sx, int sy, char mod, int who);
|
||||
void determinefinalwinner(void);
|
||||
void roadlog(char *dname, int dir, int xch, int ych, int newx, int newy);
|
||||
char getownerxy(int x, int y);
|
||||
int getownernumxy(int x, int y);
|
||||
void checkfortak(int who);
|
||||
|
|
Loading…
Reference in New Issue