// Original code used 32 bit ints and INFTY was a hard-coded 100000
// Reducing to a 16 bit int doesn't seem to have harmed the program.
#ifdef TRUE
#undef TRUE
#undef FALSE
#endif
#define TRUE 1
#define FALSE 0
#define mob_wt 6
#define back_wt 4
#define cent_wt 4
#define adv1_wt 450
#define adv2_wt 50
#define cramp_wt 6
// TO DO: if we end up with more global booleans,
// remember we can pack 8 of them into a byte to save space,
// either explicitly or using a struct containing bitfields..
static int8_t a_win;
static int8_t search_limit;
static int8_t Cancel_Request;
#define CROWN 1800
static const int8_t BACK1p[5] = { 77, 75, 73, 71, 64 };
#define BACK1(index) BACK1p[(index)-1]
static const int8_t BACK2p[5] = { 0, 2, 4, 6, 13 };
#define BACK2(index) BACK2p[(index)-1]
static const int8_t CENTSQx[8] = { 51, 53, 42, 44, 33, 35, 24, 26 };
#define CENTSQ(index) CENTSQx[index]
static const int8_t MOVEx[8] = { 9, 18, 11, 22, -9, -18, -11, -22 };
#define MOVE(index) MOVEx[index]
#include "diags.h"
#define DECLARE(type,name,low,high) type name##p[(high)-(low)+1]; type *name = &name##p[-(low)]
#define ARRAY(index,type,name,low,high) name##p[CHECK(index,#name,low,high,__LINE__)]
#define MAX_RECURSIVE_DEPTH 12
// Minimax values, to depth of recursion (max plies). So must be 16 bit.
#ifdef OLDSTYLE
DECLARE (INTEGER, MIN, 1, MAX_RECURSIVE_DEPTH);
#define MIN(index) ARRAY(index, INTEGER, MIN, 1, MAX_RECURSIVE_DEPTH)
DECLARE (INTEGER, MAX, 1, MAX_RECURSIVE_DEPTH);
#define MAX(index) ARRAY(index, INTEGER, MAX, 1, MAX_RECURSIVE_DEPTH)
#else
// wasting 2*2 bytes here to simplify code. Elements 0 are not used.
INTEGER MINp[MAX_RECURSIVE_DEPTH+1];
#define MIN(index) MINp[index]
INTEGER MAXp[MAX_RECURSIVE_DEPTH+1];
#define MAX(index) MAXp[index]
#endif
DECLARE (char, REPLY, 1, 9);
#define REPLY(index) ARRAY(index, char, REPLY, 1, 9)
#define ME 1
#define YOU 2
// Initialisation data for COMP and OPP arrays...
typedef struct Player {
int8_t COLOUR;
int8_t PLAYERNO;
int8_t POS[12]; // 1:12 still, base address is tweaked
INTEGER TYPE[12];
int8_t NUM;
int8_t NUMC;
} Player;
static const Player PLAYER1 = {
'W', // -1 - colour
ME, // 0 - player no (1 or 2)
#ifdef DEBUG_SET_POSITION
// put any set position in here for testing...
{62, 42, 55, 11, 0, 0, 0, 0, 0, 0, 0, 0}, // 1:12 - location of pieces (CPOS)
{1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000}, // 13:24 - type (eg CROWN) (CTYPE)
4, // 25 - count of pieces (CNUM)
#else
{77, 75, 73, 71, 64, 66, 62, 60, 57, 55, 53, 51}, // 1:12 - location of pieces (CPOS)
{1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000}, // 13:24 - type (eg CROWN) (CTYPE)
12, // 25 - count of pieces (CNUM)
#endif
0 // 26 - count of crowns (CNUMC)
};
// 1:12 maps to 0:11
#define PLAYER1_POS(P) PLAYER1.POS[(P)-1]
#define PLAYER1_TYPE(P) PLAYER1.TYPE[(P)-1]
static const Player PLAYER2 = {
'B', // -1 - colour
YOU, // 0 - player no (1 or 2)
#ifdef DEBUG_SET_POSITION
{33, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // 1:12 - location of pieces (OPOS)
{1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000}, // 13:24 - type (eg CROWN) (OTYPE)
2,
#else
{0, 2, 4, 6, 13, 11, 15, 17, 20, 22, 24, 26}, // 1:12 - location of pieces (OPOS)
{1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000}, // 13:24 - type (eg CROWN) (OTYPE)
12, // 25 - count of pieces (ONUM)
#endif
0 // 26 - count of crowns (ONUMC)
};
#define PLAYER2_POS(P) PLAYER2.POS[(P)-1]
#define PLAYER2_TYPE(P) PLAYER2.TYPE[(P)-1]
// These two would be better as structs...
Player COMP;
//DECLARE (INTEGER, COMP, -1, 26);
//#define COMP(index) ARRAY(index, INTEGER, COMP, -1, 26)
#define COMP_COLOUR COMP.COLOUR
#define COMP_PLAYERNO COMP.PLAYERNO
#define COMP_POS(P) COMP.POS[CHECK(P,#P,1,12,__LINE__)-1]
#define COMP_TYPE(P) COMP.TYPE[CHECK(P,#P,1,12,__LINE__)-1]
#define COMP_NUM COMP.NUM
#define COMP_NUMC COMP.NUMC
#define COMP__COLOUR COMPp->COLOUR
#define COMP__PLAYERNO COMPp->PLAYERNO
#define COMP__POS(P) COMPp->POS[CHECK(P,#P,1,12,__LINE__)-1]
#define COMP__TYPE(P) COMPp->TYPE[CHECK(P,#P,1,12,__LINE__)-1]
#define COMP__NUM COMPp->NUM
#define COMP__NUMC COMPp->NUMC
Player OPP;
//DECLARE (INTEGER, OPP, -1, 26);
//#define OPP(index) ARRAY(index, INTEGER, OPP, -1, 26)
#define OPP_COLOUR OPP.COLOUR
#define OPP_PLAYERNO OPP.PLAYERNO
#define OPP_POS(P) OPP.POS[CHECK(P,#P,1,12,__LINE__)-1]
#define OPP_TYPE(P) OPP.TYPE[CHECK(P,#P,1,12,__LINE__)-1]
#define OPP_NUM OPP.NUM
#define OPP_NUMC OPP.NUMC
#define OPP__COLOUR OPPp->COLOUR
#define OPP__PLAYERNO OPPp->PLAYERNO
#define OPP__POS(P) OPPp->POS[CHECK(P,#P,1,12,__LINE__)-1]
#define OPP__TYPE(P) OPPp->TYPE[CHECK(P,#P,1,12,__LINE__)-1]
#define OPP__NUM OPPp->NUM
#define OPP__NUMC OPPp->NUMC
#ifdef OLDSTYLE
DECLARE (int8_t, PSTACK, 1, MAX_RECURSIVE_DEPTH); // piece position take stack
#define PSTACK(index) ARRAY(index, int8_t, PSTACK, 1, MAX_RECURSIVE_DEPTH)
DECLARE (INTEGER, TSTACK, 1, MAX_RECURSIVE_DEPTH); // piece type stack
#define TSTACK(index) ARRAY(index, INTEGER, TSTACK, 1, MAX_RECURSIVE_DEPTH)
DECLARE (int8_t, NSTACK, 1, MAX_RECURSIVE_DEPTH); // piece number stack
#define NSTACK(index) ARRAY(index, int8_t, NSTACK, 1, MAX_RECURSIVE_DEPTH)
#else
// waste a byte to simplify code later... we can afford to be profligate with
// RAM now that we have reduced the footprint enough that everything fits,
// including 12 levels of recursion for the main evaluation code.
int8_t PSTACKp[MAX_RECURSIVE_DEPTH+1];
#define PSTACK(index) PSTACKp[index]
INTEGER TSTACKp[MAX_RECURSIVE_DEPTH+1];
#define TSTACK(index) TSTACKp[index]
int8_t NSTACKp[MAX_RECURSIVE_DEPTH+1];
#define NSTACK(index) NSTACKp[index]
#endif
static int8_t SP; // stack pointer
INTEGER VALUEB, NODES; // MUST be 16-bits
int8_t P, M, PIECE, DIF, MODIF, MORE, best_piece, best_move, best_take, JMAN, POS, OLDPOS, NEWPOS, LASTPOS, COMPOS, ply_number, expected_move;
//char A, B, C;
static int8_t First_player_was;
#ifdef PIZERO
void DEBUG_EVERYTHING(int line) {
int8_t P, I, J, POS;
int8_t BOARDp[80];
#define BOARD(index) BOARDp[(index)+1]
if (!logfile) return;
fprintf(logfile, "-- %d -- %ld\n", line, SP);
for (I = 0; I <= 79; I++) BOARDp[I] = ' ';
// BOARD is not really needed, can move to board locations with
// cursor addressing on linux or vector graphics on Vectrex
for (I = 0; I <= 7; I++) {
for (J = 0; J <= 6; J += 2) {
BOARD (10 * I + J + (I & 1)) = '#';
}
}
for (I = 1; I <= 12; I++) {
if (I <= COMP_NUM) {
POS = COMP_POS(I);
BOARD (POS) = (CKTYPE(COMP_TYPE(I)) == CROWN) ? 'X' : 'x';
}
if (I <= OPP_NUM) {
POS = OPP_POS(I);
BOARD (POS) = (CKTYPE(OPP_TYPE(I)) == CROWN) ? 'O' : 'o';
}
}
fprintf(logfile, "\n A B C D E F G H");
for (I = 70; I >= 0; I -= 10) {
fputc('\n', logfile);
fputc((char) (I / 10 + '1'), logfile);
for (J = 0; J <= 7; J++) {
fputc(' ', logfile);
fputc((char) BOARD (J + I), logfile);
}
fputc(' ', logfile);
fputc((char) (I / 10 + '1'), logfile);
}
fprintf(logfile, "\n A B C D E F G H\n\n");
fprintf(logfile, "COMP NUM %d NUMC %d\n", COMP_NUM, COMP_NUMC);
fprintf(logfile, "COMP POS ");
for (P = 0; P <= 11; P++) {
fprintf(logfile, "%d ", COMP.POS[P]);
}
fprintf(logfile, "\n");
fprintf(logfile, "COMP TYPE ");
for (P = 0; P <= 11; P++) {
fprintf(logfile, "%d ", COMP.TYPE[P]);
}
fprintf(logfile, "\n");
fprintf(logfile, "OPP NUM %d NUMC %d\n", OPP_NUM, OPP_NUMC);
fprintf(logfile, "OPP POS ");
for (P = 0; P <= 11; P++) {
fprintf(logfile, "%d ", OPP.POS[P]);
}
fprintf(logfile, "\n");
fprintf(logfile, "OPP TYPE ");
for (P = 0; P <= 11; P++) {
fprintf(logfile, "%d ", OPP.TYPE[P]);
}
fprintf(logfile, "\n");
fflush(logfile);
}
#endif
#ifndef PIZERO
#include <vectrex.h>
#include "controller.h"
#endif
#define FULLBRIGHT 127
#define BACKGROUND_INTENSITY 30 /* 70 */
// Vectrex brightness must be set so that board grid is faint, matching what you see in Vide
#define WHITE_INTENSITY 90
#define BLACK_INTENSITY 50
#define DIM 40
#define MAXDIM (127-40)
static int8_t Dim;
static int8_t Flash; // increments every frame with wrap-around
#define BIG_SCALE 0x7F
#define SMALL_SCALE 0x1F
#define MEDIUM_SCALE 0x5A
#ifdef PIZERO
#define TINY_SCALE 0x4
#define TINY_SCALE_CROWNED 0x2
#else
#define TINY_SCALE 0x1
#define TINY_SCALE_CROWNED 0x2
#endif
static inline void set_scale (unsigned int s) {
#ifdef PIZERO
current_scale = s;
#else
VIA_t1_cnt_lo = s;
#endif
}