Knight-Path 1.0.D018

/home/archives/knight-path/branch.1/branch.0/delta5682.018/knight-path/position.cc

Go to the documentation of this file.
00001 //
00002 // knight-path - shortest knight path between two squares
00003 // Copyright (C) 2011 Peter Miller
00004 //
00005 // This program is free software; you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation; either version 3 of the License, or (at
00008 // your option) any later version.
00009 //
00010 // This program is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 // General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License along
00016 // with this program. If not, see <http://www.gnu.org/licenses/>.
00017 //
00018 
00019 #include <cassert>
00020 #include <cstdlib>
00021 
00022 #include <knight-path/position.h>
00023 
00024 
00025 position::~position()
00026 {
00027 }
00028 
00029 
00030 position::position() :
00031     p(~0u)
00032 {
00033 }
00034 
00035 
00036 static char
00037 safe_tolower(char c)
00038 {
00039     if (isupper((unsigned char)c))
00040         return tolower((unsigned char)c);
00041     return c;
00042 }
00043 
00044 
00045 position::position(char rank, char file) :
00046     p((rank - '1') * 8 + (safe_tolower(file) - 'a'))
00047 {
00048     assert(rank >= '1');
00049     assert(rank <= '8');
00050     assert(safe_tolower(file) >= 'a');
00051     assert(safe_tolower(file) <= 'h');
00052     assert(valid());
00053 }
00054 
00055 
00056 position::position(int x, int y) :
00057     p(y * 8 + x)
00058 {
00059     assert(x >= 0);
00060     assert(x < 8);
00061     assert(y >= 0);
00062     assert(y < 8);
00063     assert(valid());
00064 }
00065 
00066 
00067 position::position(const position &rhs) :
00068     p(rhs.p)
00069 {
00070 }
00071 
00072 
00073 position &
00074 position::operator=(const position &rhs)
00075 {
00076     if (this != &rhs)
00077         p = rhs.p;
00078     return *this;
00079 }
00080 
00081 
00082 bool
00083 position::valid(void)
00084     const
00085 {
00086     return (p < 64);
00087 }
00088 
00089 
00090 char
00091 position::get_rank(void)
00092     const
00093 {
00094     return ('1' + get_y());
00095 }
00096 
00097 
00098 int
00099 position::get_y(void)
00100     const
00101 {
00102     assert(valid());
00103     return (p / 8);
00104 }
00105 
00106 
00107 char
00108 position::get_file(void)
00109     const
00110 {
00111     return ('A' + get_x());
00112 }
00113 
00114 
00115 int
00116 position::get_x(void)
00117     const
00118 {
00119     assert(valid());
00120     return (p % 8);
00121 }
00122 
00123 
00124 static inline bool
00125 safe_isspace(char c)
00126 {
00127     return isspace((unsigned char)c);
00128 
00129 }
00130 
00131 
00132 position
00133 position::read(std::istream &is)
00134 {
00135     char file_c;
00136     is >> file_c;
00137     while (safe_isspace(file_c))
00138     {
00139         // discard leading white space
00140         is >> file_c;
00141     }
00142     switch (file_c)
00143     {
00144     case 'a': case 'b': case 'c': case 'd':
00145     case 'e': case 'f': case 'g': case 'h':
00146     case 'A': case 'B': case 'C': case 'D':
00147     case 'E': case 'F': case 'G': case 'H':
00148         break;
00149 
00150     default:
00151         yuck:
00152         std::cerr << "position expected" << std::endl;
00153         exit(EXIT_FAILURE);
00154     }
00155     char rank_c;
00156     is >> rank_c;
00157     switch (rank_c)
00158     {
00159     case '1': case '2': case '3': case '4':
00160     case '5': case '6': case '7': case '8':
00161         break;
00162 
00163     default:
00164         goto yuck;
00165     }
00166     return position(rank_c, file_c);
00167 }
00168 
00169 
00170 void
00171 position::write(std::ostream &os)
00172     const
00173 {
00174     os << get_file();
00175     os << get_rank();
00176 }
00177 
00178 
00179 bool
00180 position::operator==(const position &rhs)
00181     const
00182 {
00183     assert(valid());
00184     assert(rhs.valid());
00185     return (p == rhs.p);
00186 }
00187 
00188 
00189 bool
00190 position::operator!=(const position &rhs)
00191     const
00192 {
00193     assert(valid());
00194     assert(rhs.valid());
00195     return (p != rhs.p);
00196 }
00197 
00198 
00199 position::list_t
00200 position::knight_moves(void)
00201     const
00202 {
00203     int x = get_x();
00204     int y = get_y();
00205     list_t result;
00206     if (x - 2 >= 0)
00207     {
00208         if (y - 1 >= 0)
00209             result.push_back(position(x - 2, y - 1));
00210         if (y + 1 < 8)
00211             result.push_back(position(x - 2, y + 1));
00212     }
00213     if (x - 1 >= 0)
00214     {
00215         if (y - 2 >= 0)
00216             result.push_back(position(x - 1, y - 2));
00217         if (y + 2 < 8)
00218             result.push_back(position(x - 1, y + 2));
00219     }
00220     if (x + 1 < 8)
00221     {
00222         if (y - 2 >= 0)
00223             result.push_back(position(x + 1, y - 2));
00224         if (y + 2 < 8)
00225             result.push_back(position(x + 1, y + 2));
00226     }
00227     if (x + 2 < 8)
00228     {
00229         if (y - 1 >= 0)
00230             result.push_back(position(x + 2, y - 1));
00231         if (y + 1 < 8)
00232             result.push_back(position(x + 2, y + 1));
00233     }
00234     return result;
00235 }
00236 
00237 
00238 void
00239 position::plot(char board[8][8], char c)
00240     const
00241 {
00242     board[get_y()][get_x()] = c;
00243 }
00244 
00245 
00246 int
00247 position::distance(const position &other)
00248     const
00249 {
00250     return (abs(get_x() - other.get_x()) + abs(get_y() - other.get_y()));
00251 }