HW3: working on refactor
This commit is contained in:
parent
3539cd9a71
commit
8b59fedabd
1 changed files with 225 additions and 220 deletions
|
@ -17,12 +17,6 @@
|
|||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
struct position {
|
||||
unsigned int column;
|
||||
unsigned int row;
|
||||
struct position* next;
|
||||
};
|
||||
|
||||
#if DEBUG
|
||||
char* NAMES[] = { "KING", "QUEEN", "ROOK", "BISHOP", "KNIGHT", "PAWN" };
|
||||
|
||||
|
@ -30,15 +24,6 @@ void print_p_position(struct piece_position* p) {
|
|||
printf("%s at row: %u col: %u\n", NAMES[p->piece], p->row, p->column);
|
||||
}
|
||||
|
||||
void print_poss(struct position* poss, struct piece_position* p) {
|
||||
printf("%s (r%u,c%u): moves ", NAMES[p->piece], p->row, p->column);
|
||||
while(poss != NULL) {
|
||||
printf("(r%u,c%u) ", poss->row, poss->column);
|
||||
poss = poss->next;
|
||||
}
|
||||
puts("");
|
||||
}
|
||||
|
||||
void print_visited(const struct chessboard* ch, bool* v) {
|
||||
for (int r = rows(ch) - 1; r >= 0; r--) {
|
||||
for (int c = 0; c < columns(ch); c++) {
|
||||
|
@ -49,211 +34,9 @@ void print_visited(const struct chessboard* ch, bool* v) {
|
|||
}
|
||||
#endif
|
||||
|
||||
void prepend(struct position** poss_p, unsigned column, unsigned row) {
|
||||
struct position* prev = *poss_p;
|
||||
*poss_p = malloc(sizeof(struct position));
|
||||
assert(*poss_p != NULL);
|
||||
(*poss_p)->column = column;
|
||||
(*poss_p)->row = row;
|
||||
(*poss_p)->next = prev;
|
||||
}
|
||||
|
||||
struct position* pawn_positions(const struct chessboard* c,
|
||||
struct piece_position* p) {
|
||||
struct position* poss = NULL;
|
||||
|
||||
if (p->row + 1 < rows(c)) {
|
||||
prepend(&poss, p->column, p->row + 1);
|
||||
}
|
||||
|
||||
return poss;
|
||||
}
|
||||
|
||||
struct position* king_positions(const struct chessboard* c,
|
||||
struct piece_position* p) {
|
||||
struct position* poss = NULL;
|
||||
unsigned cs = columns(c) - 1;
|
||||
unsigned rs = rows(c) - 1;
|
||||
unsigned row = p->row, col = p->column;
|
||||
|
||||
if (row > 0 && col > 0) prepend(&poss, col - 1, row - 1);
|
||||
if (row > 0) prepend(&poss, col, row - 1);
|
||||
if (row > 0 && col < cs) prepend(&poss, col + 1, row - 1);
|
||||
if (col > 0) prepend(&poss, col - 1, row);
|
||||
if (col < cs) prepend(&poss, col + 1, row);
|
||||
if (row < rs && col > 0) prepend(&poss, col - 1, row + 1);
|
||||
if (row < rs) prepend(&poss, col, row + 1);
|
||||
if (row < rs && col < cs) prepend(&poss, col + 1, row + 1);
|
||||
|
||||
return poss;
|
||||
}
|
||||
|
||||
struct position* rook_positions(const struct chessboard* c,
|
||||
struct piece_position* p, struct position* other) {
|
||||
struct position* poss = other;
|
||||
unsigned c_cols = columns(c);
|
||||
unsigned c_rows = rows(c);
|
||||
|
||||
for (int col = 0; col < c_cols; col++) {
|
||||
if (col == p->column) continue;
|
||||
prepend(&poss, col, p->row);
|
||||
}
|
||||
|
||||
for (int row = 0; row < c_rows; row++) {
|
||||
if (row == p->row) continue;
|
||||
prepend(&poss, p->column, row);
|
||||
}
|
||||
|
||||
return poss;
|
||||
}
|
||||
|
||||
struct position* knight_positions(const struct chessboard* c,
|
||||
struct piece_position* p) {
|
||||
struct position* poss = NULL;
|
||||
unsigned cs = columns(c) - 1;
|
||||
unsigned rs = rows(c) - 1;
|
||||
unsigned row = p->row, col = p->column;
|
||||
|
||||
if (row >= 1 && col >= 2) prepend(&poss, col - 2, row - 1);
|
||||
if (row >= 2 && col >= 1) prepend(&poss, col - 1, row - 2);
|
||||
if (row >= 2 && col <= cs - 1) prepend(&poss, col + 1, row - 2);
|
||||
if (row >= 1 && col <= cs - 2) prepend(&poss, col + 2, row - 1);
|
||||
if (row <= rs - 1 && col <= cs - 2) prepend(&poss, col + 2, row + 1);
|
||||
if (row <= rs - 2 && col <= cs - 1) prepend(&poss, col + 1, row + 2);
|
||||
if (row <= rs - 2 && col >= 1) prepend(&poss, col - 1, row + 2);
|
||||
if (row <= rs - 1 && col >= 2) prepend(&poss, col - 2, row + 1);
|
||||
|
||||
return poss;
|
||||
}
|
||||
|
||||
struct position* bishop_positions(const struct chessboard* board,
|
||||
struct piece_position* p) {
|
||||
struct position* poss = NULL;
|
||||
unsigned cs = columns(board);
|
||||
unsigned rs = rows(board);
|
||||
int r, c;
|
||||
|
||||
for (r = p->row - 1, c = p->column - 1; r >= 0 && c >= 0; r--, c--) {
|
||||
prepend(&poss, c, r);
|
||||
}
|
||||
|
||||
for (r = p->row + 1, c = p->column + 1; r < rs && c < cs; r++, c++) {
|
||||
prepend(&poss, c, r);
|
||||
}
|
||||
|
||||
for (r = p->row - 1, c = p->column + 1; r >= 0 && c < cs; r--, c++) {
|
||||
prepend(&poss, c, r);
|
||||
}
|
||||
|
||||
for (r = p->row + 1, c = p->column - 1; r < rs && c >= 0; r++, c--) {
|
||||
prepend(&poss, c, r);
|
||||
}
|
||||
|
||||
return poss;
|
||||
}
|
||||
|
||||
struct position* queen_positions(const struct chessboard* c,
|
||||
struct piece_position* p) {
|
||||
|
||||
struct position* canotaggio = bishop_positions(c, p);
|
||||
return rook_positions(c, p, canotaggio);
|
||||
}
|
||||
|
||||
struct position* get_positions(const struct chessboard* c,
|
||||
struct piece_position* p) {
|
||||
struct position* poss;
|
||||
switch (p->piece) {
|
||||
case PAWN: poss = pawn_positions(c, p); break;
|
||||
case KING: poss = king_positions(c, p); break;
|
||||
case ROOK: poss = rook_positions(c, p, NULL); break;
|
||||
case KNIGHT: poss = knight_positions(c, p); break;
|
||||
case BISHOP: poss = bishop_positions(c, p); break;
|
||||
case QUEEN: poss = queen_positions(c, p); break;
|
||||
}
|
||||
#if DEBUG
|
||||
print_poss(poss, p);
|
||||
#endif
|
||||
return poss;
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned int increasing_path_len(const struct chessboard* c,
|
||||
struct piece_position* p) {
|
||||
|
||||
unsigned int hops = 0;
|
||||
bool has_next = true;
|
||||
|
||||
#if DEBUG
|
||||
puts("increasing");
|
||||
printf("board r=%u c=%u\n", rows(c), columns(c));
|
||||
#endif
|
||||
|
||||
while (has_next) {
|
||||
struct position* poss = get_positions(c, p);
|
||||
unsigned int base_val = value_at(c, p->column, p->row), next_v;
|
||||
has_next = false;
|
||||
|
||||
#if DEBUG
|
||||
print_p_position(p);
|
||||
#endif
|
||||
|
||||
while(poss != NULL) {
|
||||
next_v = value_at(c, poss->column, poss->row);
|
||||
if (next_v > base_val) {
|
||||
has_next = true;
|
||||
p->row = poss->row;
|
||||
p->column = poss->column;
|
||||
base_val = next_v;
|
||||
}
|
||||
struct position* del = poss;
|
||||
poss = poss->next;
|
||||
free(del);
|
||||
}
|
||||
|
||||
hops++;
|
||||
}
|
||||
|
||||
return hops - 1;
|
||||
}
|
||||
|
||||
unsigned int decreasing_path_len(const struct chessboard* c,
|
||||
struct piece_position* p) {
|
||||
|
||||
unsigned int hops = 0;
|
||||
bool has_next = true;
|
||||
|
||||
#if DEBUG
|
||||
puts("decreasing");
|
||||
printf("board r=%u c=%u\n", rows(c), columns(c));
|
||||
#endif
|
||||
|
||||
while (has_next) {
|
||||
struct position* poss = get_positions(c, p);
|
||||
unsigned int base_val = value_at(c, p->column, p->row), next_v;
|
||||
has_next = false;
|
||||
|
||||
#if DEBUG
|
||||
print_p_position(p);
|
||||
#endif
|
||||
|
||||
while(poss != NULL) {
|
||||
if ((next_v = value_at(c, poss->column, poss->row)) < base_val) {
|
||||
has_next = true;
|
||||
p->row = poss->row;
|
||||
p->column = poss->column;
|
||||
base_val = next_v;
|
||||
}
|
||||
struct position* del = poss;
|
||||
poss = poss->next;
|
||||
free(del);
|
||||
}
|
||||
|
||||
hops++;
|
||||
}
|
||||
|
||||
return hops - 1;
|
||||
}
|
||||
/**
|
||||
* Code for visited row/column dictionary. Used in simple_path_len
|
||||
*/
|
||||
|
||||
struct row_list {
|
||||
unsigned row;
|
||||
|
@ -337,6 +120,228 @@ void table_destroy(const struct chessboard* c, visit_table* visited) {
|
|||
free(visited);
|
||||
}
|
||||
|
||||
/**
|
||||
* Code for search_status struct. Used to keep track of the piece to choose in
|
||||
* all *_path_len functions and in piece functions
|
||||
*/
|
||||
|
||||
struct search_status {
|
||||
unsigned column;
|
||||
unsigned row;
|
||||
bool found;
|
||||
|
||||
bool (*better)(struct search_status* s, unsigned col, unsigned row);
|
||||
|
||||
const struct chessboard* chessboard;
|
||||
visit_table* table;
|
||||
};
|
||||
|
||||
void search_status_init(struct search_status* s, struct piece_position* p,
|
||||
bool (*better)(struct search_status*, unsigned, unsigned),
|
||||
const struct chessboard* c, visit_table* table) {
|
||||
s->column = p->column;
|
||||
s->row = p->row;
|
||||
s->found = false;
|
||||
s->better = better;
|
||||
s->chessboard = c;
|
||||
s->table = table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Consider compares the value at the given position with the current maximum,
|
||||
* if "better" (according to the predicate stored in search_status) then it sets
|
||||
* the search_status maximum to the given posiition
|
||||
*/
|
||||
|
||||
void consider(struct search_status* s, unsigned column, unsigned row) {
|
||||
if (s->better(s, column, row)) {
|
||||
s->found = true;
|
||||
s->column = column;
|
||||
s->row = row;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Piece postitions. They "consider" every position which is a legal move for
|
||||
* the piece
|
||||
*/
|
||||
|
||||
void pawn_positions(struct search_status* s, struct piece_position* p) {
|
||||
if (p->row + 1 < rows(s->chessboard)) {
|
||||
consider(s, p->column, p->row + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void king_positions(struct search_status* s, struct piece_position* p) {
|
||||
unsigned cs = columns(s->chessboard) - 1;
|
||||
unsigned rs = rows(s->chessboard) - 1;
|
||||
unsigned row = p->row, col = p->column;
|
||||
|
||||
if (row > 0 && col > 0) consider(s, col - 1, row - 1);
|
||||
if (row > 0) consider(s, col, row - 1);
|
||||
if (row > 0 && col < cs) consider(s, col + 1, row - 1);
|
||||
if (col > 0) consider(s, col - 1, row);
|
||||
if (col < cs) consider(s, col + 1, row);
|
||||
if (row < rs && col > 0) consider(s, col - 1, row + 1);
|
||||
if (row < rs) consider(s, col, row + 1);
|
||||
if (row < rs && col < cs) consider(s, col + 1, row + 1);
|
||||
}
|
||||
|
||||
void rook_positions(struct search_status* s, struct piece_position* p) {
|
||||
unsigned c_cols = columns(s->chessboard);
|
||||
unsigned c_rows = rows(s->chessboard);
|
||||
|
||||
for (int col = 0; col < c_cols; col++) {
|
||||
if (col == p->column) continue;
|
||||
consider(s, col, p->row);
|
||||
}
|
||||
|
||||
for (int row = 0; row < c_rows; row++) {
|
||||
if (row == p->row) continue;
|
||||
consider(s, p->column, row);
|
||||
}
|
||||
}
|
||||
|
||||
void knight_positions(struct search_status* s, struct piece_position* p) {
|
||||
unsigned cs = columns(s->chessboard) - 1;
|
||||
unsigned rs = rows(s->chessboard) - 1;
|
||||
unsigned row = p->row, col = p->column;
|
||||
|
||||
if (row >= 1 && col >= 2) consider(s, col - 2, row - 1);
|
||||
if (row >= 2 && col >= 1) consider(s, col - 1, row - 2);
|
||||
if (row >= 2 && col <= cs - 1) consider(s, col + 1, row - 2);
|
||||
if (row >= 1 && col <= cs - 2) consider(s, col + 2, row - 1);
|
||||
if (row <= rs - 1 && col <= cs - 2) consider(s, col + 2, row + 1);
|
||||
if (row <= rs - 2 && col <= cs - 1) consider(s, col + 1, row + 2);
|
||||
if (row <= rs - 2 && col >= 1) consider(s, col - 1, row + 2);
|
||||
if (row <= rs - 1 && col >= 2) consider(s, col - 2, row + 1);
|
||||
}
|
||||
|
||||
void bishop_positions(struct search_status* s, struct piece_position* p) {
|
||||
unsigned cs = columns(s->chessboard);
|
||||
unsigned rs = rows(s->chessboard);
|
||||
int r, c;
|
||||
|
||||
for (r = p->row - 1, c = p->column - 1; r >= 0 && c >= 0; r--, c--) {
|
||||
consider(s, c, r);
|
||||
}
|
||||
|
||||
for (r = p->row + 1, c = p->column + 1; r < rs && c < cs; r++, c++) {
|
||||
consider(s, c, r);
|
||||
}
|
||||
|
||||
for (r = p->row - 1, c = p->column + 1; r >= 0 && c < cs; r--, c++) {
|
||||
consider(s, c, r);
|
||||
}
|
||||
|
||||
for (r = p->row + 1, c = p->column - 1; r < rs && c >= 0; r++, c--) {
|
||||
consider(s, c, r);
|
||||
}
|
||||
}
|
||||
|
||||
void queen_positions(struct search_status* canotaggio,
|
||||
struct piece_position* p) {
|
||||
|
||||
bishop_positions(canotaggio, p);
|
||||
rook_positions(canotaggio, p);
|
||||
}
|
||||
|
||||
void consider_positions(struct search_status* s, struct piece_position* p) {
|
||||
switch (p->piece) {
|
||||
case PAWN: pawn_positions(s, p); break;
|
||||
case KING: king_positions(s, p); break;
|
||||
case ROOK: rook_positions(s, p); break;
|
||||
case KNIGHT: knight_positions(s, p); break;
|
||||
case BISHOP: bishop_positions(s, p); break;
|
||||
case QUEEN: queen_positions(s, p); break;
|
||||
}
|
||||
#if DEBUG
|
||||
print_poss(poss, p);
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned int path_len(const struct chessboard* c,
|
||||
struct piece_position* p,
|
||||
bool (*better)(struct search_status*, unsigned, unsigned),
|
||||
visit_table* table) {
|
||||
|
||||
unsigned int hops = 0;
|
||||
bool has_next = true;
|
||||
|
||||
#if DEBUG
|
||||
printf("board r=%u c=%u\n", rows(c), columns(c));
|
||||
#endif
|
||||
|
||||
struct search_status status;
|
||||
search_status_init(&status, p, better, c, table);
|
||||
|
||||
while (has_next) {
|
||||
consider_positions(&status, p);
|
||||
has_next = status.found;
|
||||
p->column = status.column;
|
||||
p->row = status.row;
|
||||
|
||||
#if DEBUG
|
||||
print_p_position(p);
|
||||
#endif
|
||||
|
||||
hops++;
|
||||
}
|
||||
|
||||
return hops - 1;
|
||||
}
|
||||
|
||||
|
||||
bool better_inc(struct search_status* s, unsigned column, unsigned row) {
|
||||
return value_at(s->chessboard, s->column, s->row) >
|
||||
value_at(s->chessboard, column, row);
|
||||
}
|
||||
|
||||
bool better_dec(struct search_status* s, unsigned column, unsigned row) {
|
||||
return value_at(s->chessboard, s->column, s->row) <
|
||||
value_at(s->chessboard, column, row);
|
||||
}
|
||||
|
||||
bool better_simple(struct search_status* s, unsigned column, unsigned row) {
|
||||
return !table_visited(s->chessboard, s->table, column, row) &&
|
||||
(!s->found || (value_at(s->chessboard, s->column, s->row) >
|
||||
value_at(s->chessboard, column, row)));
|
||||
}
|
||||
|
||||
unsigned int increasing_path_len(const struct chessboard* c,
|
||||
struct piece_position* p) {
|
||||
|
||||
}
|
||||
|
||||
unsigned int decreasing_path_len(const struct chessboard* c,
|
||||
struct piece_position* p) {
|
||||
|
||||
unsigned int hops = 0;
|
||||
bool has_next = true;
|
||||
|
||||
#if DEBUG
|
||||
puts("decreasing");
|
||||
printf("board r=%u c=%u\n", rows(c), columns(c));
|
||||
#endif
|
||||
|
||||
struct search_status status;
|
||||
search_status_init(&status, p, better_inc, c, NULL);
|
||||
|
||||
while (has_next) {
|
||||
consider_positions(&status, p);
|
||||
has_next = status.found;
|
||||
p->column = status.column;
|
||||
p->row = status.row;
|
||||
|
||||
#if DEBUG
|
||||
print_p_position(p);
|
||||
#endif
|
||||
|
||||
hops++;
|
||||
}
|
||||
|
||||
return hops - 1;
|
||||
}
|
||||
unsigned int simple_path_len(const struct chessboard* c,
|
||||
struct piece_position* p) {
|
||||
|
||||
|
|
Reference in a new issue