// 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 }