From 13c8a836d307e78c62dc19dd2dd27b2f119cb1af Mon Sep 17 00:00:00 2001 From: Claudio Maggioni Date: Tue, 10 Dec 2019 16:47:44 +0100 Subject: [PATCH] HW3: done --- chess_paths/chess_paths.c | 302 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 302 insertions(+) create mode 100644 chess_paths/chess_paths.c diff --git a/chess_paths/chess_paths.c b/chess_paths/chess_paths.c new file mode 100644 index 0000000..d9f40ef --- /dev/null +++ b/chess_paths/chess_paths.c @@ -0,0 +1,302 @@ +// vim: set ts=4 sw=4 et tw=80: + +#include "chess_paths.h" +#include +#include +#include +#include + + +struct position { + unsigned int column; + unsigned int row; + struct position* next; +}; + +char* NAMES[] = { "KING", "QUEEN", "ROOK", "BISHOP", "KNIGHT", "PAWN" }; + +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++) { + printf("%d", v[columns(ch) * c + r]); + } + puts(""); + } +} + +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* malusa = bishop_positions(c, p); + return rook_positions(c, p, malusa); +} + +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; +} + +void visit(bool* visited, unsigned columns, unsigned column, unsigned row) { + visited[column * columns + row] = true; +} + +bool visited(bool* visited, unsigned columns, unsigned column, unsigned row) { + return visited[column * columns + row]; +} + +unsigned int simple_path_len(const struct chessboard* c, + struct piece_position* p) { + + const unsigned int CC = columns(c); + bool* v = calloc(rows(c) * CC, sizeof(unsigned)); + visit(v, CC, p->column, p->row); +#if DEBUG + print_visited(c, v); +#endif + + bool has_next = true; + unsigned hops = 0; + + while(has_next) { + struct position* poss = get_positions(c, p); + has_next = false; + unsigned int base_v = 0, next_v; + +#if DEBUG + puts("simple"); + print_p_position(p); +#endif + + while(poss != NULL) { + if (!visited(v, CC, poss->column, poss->row)) { + next_v = value_at(c, poss->column, poss->row); + if (!has_next || next_v > base_v) { + has_next = true; + p->row = poss->row; + p->column = poss->column; + base_v = next_v; + } + } + struct position* del = poss; + poss = poss->next; + free(del); + } + + visit(v, CC, p->column, p->row); +#if DEBUG + print_visited(c, v); +#endif + hops++; + } + + free(v); + return hops - 1; +} +