#include "penguin.hpp" #include <sstream> using namespace std; namespace game { penguin::penguin() { //Update moves on all penguins uint64_t obstacles = (~(state.one_fish | state.two_fish | state.three_fish)); obstacles |= ((uint64_t) 1) << (state.p1_red & 63); obstacles |= ((uint64_t) 1) << (state.p2_red & 63); obstacles |= ((uint64_t) 1) << (state.p3_red & 63); obstacles |= ((uint64_t) 1) << (state.p4_red & 63); obstacles |= ((uint64_t) 1) << (state.p1_blue & 63); obstacles |= ((uint64_t) 1) << (state.p2_blue & 63); obstacles |= ((uint64_t) 1) << (state.p3_blue & 63); obstacles |= ((uint64_t) 1) << (state.p4_blue & 63); state.nb_moves_red = 0; state.nb_moves_blue = 0; state.nb_moves_red += update_moves(&state.p1_red, obstacles); state.nb_moves_red += update_moves(&state.p2_red, obstacles); state.nb_moves_red += update_moves(&state.p3_red, obstacles); state.nb_moves_red += update_moves(&state.p4_red, obstacles); state.nb_moves_blue += update_moves(&state.p1_blue, obstacles); state.nb_moves_blue += update_moves(&state.p2_blue, obstacles); state.nb_moves_blue += update_moves(&state.p3_blue, obstacles); state.nb_moves_blue += update_moves(&state.p4_blue, obstacles); //Change player if the other one can play if(state.current_player_red && state.nb_moves_blue > 0) state.current_player_red = false; else if(state.current_player_red == false && state.nb_moves_red > 0) state.current_player_red = true; } shared_ptr<game<penguin_state>> penguin::do_copy() const { return shared_ptr<penguin>(new penguin(*this)); } penguin_state penguin::get_state() { return state; } void penguin::set_state(const penguin_state& s) { state = s; } bool penguin::end_of_game() const { return state.nb_moves_red == 0 && state.nb_moves_blue == 0; } bool penguin::won(std::uint8_t player) const { if (player == RED) return state.score_red > state.score_blue; return state.score_blue > state.score_red; } bool penguin::lost(std::uint8_t player) const { if(player == RED) return state.score_red < state.score_blue; return state.score_blue < state.score_red; } bool penguin::draw(std::uint8_t player) const { return state.score_blue == state.score_red; } uint8_t penguin::current_player() const { return state.current_player_red ? RED : BLUE; } int penguin::value(uint8_t player) const { if (won(player)) return 1; else if (lost(player)) return -1; else return 0; } /* Number of moves that you can play */ uint16_t penguin::number_of_moves() const { //return 9 - state.total_moves; return 0; } /* The penguin that will move if we want to play the #move_number move in the list of possible moves. * What this function does: * Find the penguin that will move. * Change its total number of moves so that it is relative to that penguin's possible moves and not relative to ALL the penguins' moves. * Return a pointer to that penguin * */ uint32_t* penguin::penguin_that_moves(uint16_t move_number) { if(state.current_player_red) { if(((state.p1_red >> 6) & 63) > move_number) { uint32_t* p = &state.p1_red; (*p) = (*p) & 0xFFFFF03F; //Reset move number for the penguin to 0 (*p) = (*p) | ((uint32_t) move_number) << 6; return p; } move_number -= (state.p1_red >> 6) & 63; if(((state.p2_red >> 6) & 63) > move_number) { uint32_t* p = &state.p2_red; (*p) = (*p) & 0xFFFFF03F; //Reset move number for the penguin to 0 (*p) = (*p) | ((uint32_t) move_number) << 6; return p; } move_number -= (state.p2_red >> 6) & 63; if(((state.p3_red >> 6) & 63) > move_number) { uint32_t* p = &state.p3_red; (*p) = (*p) & 0xFFFFF03F; //Reset move number for the penguin to 0 (*p) = (*p) | ((uint32_t) move_number) << 6; return p; } move_number -= (state.p3_red >> 6) & 63; uint32_t* p = &state.p4_red; (*p) = (*p) & 0xFFFFF03F; //Reset move number for the penguin to 0 (*p) = (*p) | ((uint32_t) move_number) << 6; return p; } else { if(((state.p1_blue >> 6) & 63) > move_number) { uint32_t* p = &state.p1_blue; (*p) = (*p) & 0xFFFFF03F; //Reset move number for the penguin to 0 (*p) = (*p) | ((uint32_t) move_number) << 6; return p; } move_number -= (state.p1_blue >> 6) & 63; if(((state.p2_blue >> 6) & 63) > move_number) { uint32_t* p = &state.p2_blue; (*p) = (*p) & 0xFFFFF03F; //Reset move number for the penguin to 0 (*p) = (*p) | ((uint32_t) move_number) << 6; return p; } move_number -= (state.p2_blue >> 6) & 63; if(((state.p3_blue >> 6) & 63) > move_number) { uint32_t* p = &state.p3_blue; (*p) = (*p) & 0xFFFFF03F; //Reset move number for the penguin to 0 (*p) = (*p) | ((uint32_t) move_number) << 6; return p; } move_number -= (state.p3_blue >> 6) & 63; uint32_t* p = &state.p4_blue; (*p) = (*p) & 0xFFFFF03F; //Reset move number for the penguin to 0 (*p) = (*p) | ((uint32_t) move_number) << 6; return p; } } void penguin::move_penguin(uint32_t* p) { uint8_t move_number = ((*p) >> 6) & 63; //Move number for the current penguin uint32_t penguin_copy = (*p) >> 12; //Direction A if((penguin_copy & 7) >= move_number) { //Move direction A (*p) = (7 * move_number) + ((*p) & 63); return; } move_number -= penguin_copy & 7; penguin_copy = penguin_copy >> 3; if((penguin_copy & 7) >= move_number) { //Move direction B (*p) = (-1 * move_number) + ((*p) & 63); return; } move_number -= penguin_copy & 7; penguin_copy = penguin_copy >> 3; if((penguin_copy & 7) >= move_number) { //Move direction C (*p) = (-8 * move_number) + ((*p) & 63); return; } move_number -= penguin_copy & 7; penguin_copy = penguin_copy >> 3; if((penguin_copy & 7) >= move_number) { //Move direction D (*p) = (-7 * move_number) + ((*p) & 63); return; } move_number -= penguin_copy & 7; penguin_copy = penguin_copy >> 3; if((penguin_copy & 7) >= move_number) { //Move direction E (*p) = (1 * move_number) + ((*p) & 63); return; } move_number -= penguin_copy & 7; penguin_copy = penguin_copy >> 3; //Move direction F (*p) = (8 * move_number) + ((*p) & 63); } int penguin::update_moves(uint32_t* p, uint64_t obstacles) { #define IsFree(i) (((obstacles >> (i)) & 1) == 0) int pos = (*p) & 63; (*p) = pos; //Reset the penguin to all zeros except the position int i = pos; uint32_t nbmoves = 0; uint32_t total_moves = 0; //Direction A while(((i+7) < 60) && (i%15 != 0) && IsFree(i+7)) { i += 7; nbmoves++; total_moves++; } (*p) = (*p) | nbmoves << 12; //Direction B nbmoves = 0; i = pos; while((i%15 != 0) && (i%15 != 8) && IsFree(i-1)) { i --; nbmoves++; total_moves++; } (*p) = (*p) | nbmoves << 15; //Direction C nbmoves = 0; i = pos; while((i-8 > 0) && (i%15 != 0) && IsFree(i-8)) { i -= 8; nbmoves++; total_moves++; } (*p) = (*p) | nbmoves << 18; //Direction D nbmoves = 0; i = pos; while((i-7 > 0) && (i%15 != 7) && IsFree(i-7)) { i -= 7; nbmoves++; total_moves++; } (*p) = (*p) | nbmoves << 21; //Direction E nbmoves = 0; i = pos; while((i%15 != 7) && (i%15 != 14) && IsFree(i+1)) { i ++; nbmoves++; total_moves++; } (*p) = (*p) | nbmoves << 24; //Direction F nbmoves = 0; i = pos; while((i+8 < 60) && (i%15 != 7) && IsFree(i+8)) { i += 8; nbmoves++; total_moves++; } (*p) = (*p) | nbmoves << 27; (*p) = (*p) | total_moves << 6; return total_moves; } //Play the mth move in the possible moves list. void penguin::play(uint16_t m) { //Find which penguin will move uint32_t* p = penguin_that_moves(m); uint8_t position = (*p) & 63; //Find the value of the tile the penguin is on and update score if ((state.one_fish >> position) & 1) { if(current_player() == RED) state.score_red += 1; else state.score_blue += 1; //We replace this tile with an empty one (0 in the bitboard) state.one_fish = state.one_fish & ~(((uint64_t) 1) << position); } else if ((state.two_fish >> position) & 1) { if(current_player() == RED) state.score_red += 2; else state.score_blue += 2; //We replace this tile with an empty one (0 in the bitboard) state.two_fish = state.two_fish & ~(((uint64_t) 1) << position); } else { if(current_player() == RED) state.score_red += 3; else state.score_blue += 3; //We replace this tile with an empty one (0 in the bitboard) state.three_fish = state.three_fish & ~(((uint64_t) 1) << position); } //Move the current penguin move_penguin(p); //Update moves on all penguins uint64_t obstacles = (~(state.one_fish | state.two_fish | state.three_fish)); obstacles |= ((uint64_t) 1) << (state.p1_red & 63); obstacles |= ((uint64_t) 1) << (state.p2_red & 63); obstacles |= ((uint64_t) 1) << (state.p3_red & 63); obstacles |= ((uint64_t) 1) << (state.p4_red & 63); obstacles |= ((uint64_t) 1) << (state.p1_blue & 63); obstacles |= ((uint64_t) 1) << (state.p2_blue & 63); obstacles |= ((uint64_t) 1) << (state.p3_blue & 63); obstacles |= ((uint64_t) 1) << (state.p4_blue & 63); state.nb_moves_red = 0; state.nb_moves_blue = 0; state.nb_moves_red += update_moves(&state.p1_red, obstacles); state.nb_moves_red += update_moves(&state.p2_red, obstacles); state.nb_moves_red += update_moves(&state.p3_red, obstacles); state.nb_moves_red += update_moves(&state.p4_red, obstacles); state.nb_moves_blue += update_moves(&state.p1_blue, obstacles); state.nb_moves_blue += update_moves(&state.p2_blue, obstacles); state.nb_moves_blue += update_moves(&state.p3_blue, obstacles); state.nb_moves_blue += update_moves(&state.p4_blue, obstacles); //Change player if the other one can play if(state.current_player_red && state.nb_moves_blue > 0) state.current_player_red = false; else if(state.current_player_red == false && state.nb_moves_red > 0) state.current_player_red = true; } string penguin::player_to_string(uint8_t player) const { return player == RED ? "Red" : "Blue"; } string penguin::move_to_string(uint16_t m) const { return std::to_string(m); } set<int> penguin::to_input_vector() const { return set<int>(); } void penguin::from_input_vector(const std::set<int>& input) { } string penguin::to_string() const { string result= "--------------------"; result += "\n1 fish bro: " + std::to_string(state.one_fish); result += "\nTwo fishes: " + std::to_string(state.two_fish); result += "\nThree fish: " + std::to_string(state.three_fish); result += "\nRed p1: " + std::to_string(state.p1_red); result += "\nRed p2: " + std::to_string(state.p2_red); result += "\nRed p3: " + std::to_string(state.p3_red); result += "\nRed p4: " + std::to_string(state.p4_red); result += "\nBlue p1: " + std::to_string(state.p1_blue); result += "\nBlue p2: " + std::to_string(state.p2_blue); result += "\nBlue p3: " + std::to_string(state.p3_blue); result += "\nBlue p4: " + std::to_string(state.p4_blue); result += "\nScore R: " + std::to_string(state.score_red); result += "\nScore B: " + std::to_string(state.score_blue); result += "\nNb possible moves R:" + std::to_string(state.nb_moves_red); result += "\nNb possible moves B:" + std::to_string(state.nb_moves_blue); return result; } std::uint64_t penguin::hash() const { return 0; } std::uint64_t penguin::hash(std::uint16_t m) const { return 0; } ostream& operator<<(ostream& os, const penguin& pen) { os << pen.to_string() << endl; return os; } }