#include "opt_oware.h" void printboard(int thisside[], int otherside[]) { printf(" "); for (int i = houses - 1; i >= 0; i--) printf("%3d", otherside[i]); printf("\n%3d%*c%3d\n ", otherside[houses], houses * 3 - 2, ' ', thisside[houses]); for (int i = 0; i < houses; i++) printf("%3d", thisside[i]); } /* 1 if side is empty, 0 otherwise */ bool empty(int side[]) { if (side[0]) return false; if (side[1]) return false; if (side[2]) return false; if (side[3]) return false; if (side[4]) return false; if (side[5]) return false; return true; } /* perform move (0-5) on position thisside/otherside, but do not check some boundary conditions */ bool ply(int move, int thisside[], int otherside[]) { int seeds; int houses_to_fill = houses + (houses - 1); if (move < 0 || move >= houses) { /* fprintf(stderr,"move %d out of range\n",move);*/ return false; } seeds = thisside[move]; if (seeds == 0) { /* fprintf(stderr,"no seeds at %d\n",move);*/ return false; } thisside[move] = 0; int otherside_relative_position; int full_rounds = (seeds / houses_to_fill); int houses_filled_in_last_round = (seeds % houses_to_fill); if (0 != move) { int relative_position = 0 - move; if (relative_position < 0) { relative_position += houses_to_fill + 1; } thisside[0] += full_rounds + (relative_position <= houses_filled_in_last_round); } otherside_relative_position = 0 + houses - move; otherside[0] += full_rounds + (otherside_relative_position <= houses_filled_in_last_round); if (1 != move) { int relative_position = 1 - move; if (relative_position < 0) { relative_position += houses_to_fill + 1; } thisside[1] += full_rounds + (relative_position <= houses_filled_in_last_round); } otherside_relative_position = 1 + houses - move; otherside[1] += full_rounds + (otherside_relative_position <= houses_filled_in_last_round); if (2 != move) { int relative_position = 2 - move; if (relative_position < 0) { relative_position += houses_to_fill + 1; } thisside[2] += full_rounds + (relative_position <= houses_filled_in_last_round); } otherside_relative_position = 2 + houses - move; otherside[2] += full_rounds + (otherside_relative_position <= houses_filled_in_last_round); if (3 != move) { int relative_position = 3 - move; if (relative_position < 0) { relative_position += houses_to_fill + 1; } thisside[3] += full_rounds + (relative_position <= houses_filled_in_last_round); } otherside_relative_position = 3 + houses - move; otherside[3] += full_rounds + (otherside_relative_position <= houses_filled_in_last_round); if (4 != move) { int relative_position = 4 - move; if (relative_position < 0) { relative_position += houses_to_fill + 1; } thisside[4] += full_rounds + (relative_position <= houses_filled_in_last_round); } otherside_relative_position = 4 + houses - move; otherside[4] += full_rounds + (otherside_relative_position <= houses_filled_in_last_round); if (5 != move) { int relative_position = 5 - move; if (relative_position < 0) { relative_position += houses_to_fill + 1; } thisside[5] += full_rounds + (relative_position <= houses_filled_in_last_round); } otherside_relative_position = 5 + houses - move; otherside[5] += full_rounds + (otherside_relative_position <= houses_filled_in_last_round); /* make backup, in case of grand slam */ int tshbackup = thisside[houses]; int othersidebackup1[houses]; memcpy(othersidebackup1, otherside, HOUSES_ARRAY_SIZE); /* now check if we capture */ int remaining = seeds % houses_to_fill; if (remaining == 0) //11 % 11 is 0 but should be 11 { remaining = houses_to_fill; } bool has_captured = false; if (remaining > (houses - (move + 1)) && remaining <= (houses - (move + 1)) + houses) { int position = remaining - (houses - move); //to get the index has_captured = (otherside[position] == 2 || otherside[position] == 3); for (; position >= 0 && (otherside[position] == 2 || otherside[position] == 3); position--) { thisside[houses] += otherside[position]; otherside[position] = 0; } } /* grand slam rule: legal but no capture results */ if (has_captured && empty(otherside)) { thisside[houses] = tshbackup; memcpy(otherside, othersidebackup1, HOUSES_ARRAY_SIZE); } return !empty(otherside); } bool canmove(int thisside[], int otherside[]) { int ts[houses + 1]; int os[houses + 1]; memcpy(ts, thisside, BOARD_ARRAY_SIZE); memcpy(os, otherside, BOARD_ARRAY_SIZE); if (ply(0, ts, os)) return true; memcpy(ts, thisside, BOARD_ARRAY_SIZE); memcpy(os, otherside, BOARD_ARRAY_SIZE); if (ply(1, ts, os)) return true; memcpy(ts, thisside, BOARD_ARRAY_SIZE); memcpy(os, otherside, BOARD_ARRAY_SIZE); if (ply(2, ts, os)) return true; memcpy(ts, thisside, BOARD_ARRAY_SIZE); memcpy(os, otherside, BOARD_ARRAY_SIZE); if (ply(3, ts, os)) return true; memcpy(ts, thisside, BOARD_ARRAY_SIZE); memcpy(os, otherside, BOARD_ARRAY_SIZE); if (ply(4, ts, os)) return true; memcpy(ts, thisside, BOARD_ARRAY_SIZE); memcpy(os, otherside, BOARD_ARRAY_SIZE); if (ply(5, ts, os)) return true; return false; } /* perform move (0-5) on position thisside/otherside, including resolving game-ending conditions */ bool plyfull(int move, int thisside[], int otherside[]) { // printboard(thisside, otherside); // printf("\n"); if (!ply(move, thisside, otherside)) { // printboard(thisside, otherside); // printf("\n Move %d returning false \n", move); return false; } if (!canmove(otherside, thisside)) { // printf("Copying back \n"); thisside[houses] += thisside[0]; thisside[0] = 0; otherside[houses] += otherside[0]; otherside[0] = 0; thisside[houses] += thisside[1]; thisside[1] = 0; otherside[houses] += otherside[1]; otherside[1] = 0; thisside[houses] += thisside[2]; thisside[2] = 0; otherside[houses] += otherside[2]; otherside[2] = 0; thisside[houses] += thisside[3]; thisside[3] = 0; otherside[houses] += otherside[3]; otherside[3] = 0; thisside[houses] += thisside[4]; thisside[4] = 0; otherside[houses] += otherside[4]; otherside[4] = 0; thisside[houses] += thisside[5]; thisside[5] = 0; otherside[houses] += otherside[5]; otherside[5] = 0; } // printboard(thisside, otherside); // printf("\n Move %d returning true \n", move); return true; } /* initialize thisside and otherside from the command line arguments */ int cmdline2pos(int argc, char *argv[], int thisside[], int otherside[]) { if (argc != 2 * houses + 2) return 0; for (int i = 0; i < argc; i++) if (i <= houses) thisside[i] = atoi(argv[i]); else otherside[i - houses - 1] = atoi(argv[i]); return 1; }