00001 /* 00002 * Copyright (C) 2004 Ivo Danihelka (ivo@danihelka.net) 00003 * 00004 * This program is free software; you can redistribute it and/or modify 00005 * it under the terms of the GNU General Public License as published by 00006 * the Free Software Foundation; either version 2 of the License, or 00007 * (at your option) any later version. 00008 */ 00009 #include "MarkMask.h" 00010 00011 #include "Cube.h" 00012 #include "Shape.h" 00013 #include "Field.h" 00014 00015 #include <algorithm> 00016 00017 //----------------------------------------------------------------- 00018 MarkMask::MarkMask(Cube *model, Field *field) 00019 { 00020 m_model = model; 00021 m_field = field; 00022 } 00023 //----------------------------------------------------------------- 00024 /** 00025 * Return others which resist us to move this direction. 00026 * Pointers to NULL and own model are not included. 00027 * 00028 * @return unique pointers, not NULL 00029 */ 00030 Cube::t_models 00031 MarkMask::getResist(Dir::eDir dir) const 00032 { 00033 V2 shift = Dir::dir2xy(dir); 00034 V2 shift_loc = shift.plus(m_model->getLocation()); 00035 00036 return getPlacedResist(shift_loc); 00037 } 00038 //----------------------------------------------------------------- 00039 /** 00040 * Return others which resist at given location. 00041 * Pointers to NULL and own model are not included. 00042 * 00043 * @return unique pointers, not NULL 00044 */ 00045 Cube::t_models 00046 MarkMask::getPlacedResist(const V2 &loc) const 00047 { 00048 Cube::t_models models; 00049 const Shape *shape = m_model->shape(); 00050 Shape::const_iterator end = shape->marksEnd(); 00051 for (Shape::const_iterator i = shape->marksBegin(); i != end; ++i) { 00052 V2 mark = loc.plus(*i); 00053 00054 Cube *resist = m_field->getModel(mark); 00055 if (NULL != resist && m_model != resist) { 00056 models.push_back(resist); 00057 } 00058 } 00059 00060 std::sort(models.begin(), models.end()); 00061 Cube::t_models::iterator last = std::unique(models.begin(), models.end()); 00062 models.erase(last, models.end()); 00063 00064 return models; 00065 } 00066 //----------------------------------------------------------------- 00067 /** 00068 * Write our position to the field. 00069 */ 00070 void 00071 MarkMask::mask() 00072 { 00073 writeModel(m_model); 00074 } 00075 //----------------------------------------------------------------- 00076 /** 00077 * Clear our position from the field. 00078 */ 00079 void 00080 MarkMask::unmask() 00081 { 00082 writeModel(NULL); 00083 } 00084 //----------------------------------------------------------------- 00085 void 00086 MarkMask::writeModel(Cube *model) 00087 { 00088 V2 loc = m_model->getLocation(); 00089 const Shape *shape = m_model->shape(); 00090 Shape::const_iterator end = shape->marksEnd(); 00091 for (Shape::const_iterator i = shape->marksBegin(); i != end; ++i) { 00092 V2 mark = loc.plus(*i); 00093 m_field->setModel(mark, model); 00094 } 00095 } 00096 00097 //----------------------------------------------------------------- 00098 /** 00099 * Returns dir to out of room. 00100 * The direction must be without resist. 00101 * @return return dir or DIR_NO when model is not at the border. 00102 */ 00103 Dir::eDir 00104 MarkMask::getBorderDir() const 00105 { 00106 V2 loc = m_model->getLocation(); 00107 const Shape *shape = m_model->shape(); 00108 Shape::const_iterator end = shape->marksEnd(); 00109 for (Shape::const_iterator i = shape->marksBegin(); i != end; ++i) { 00110 V2 mark = loc.plus(*i); 00111 if (mark.getX() == 0 && isBorderDir(Dir::DIR_LEFT)) { 00112 return Dir::DIR_LEFT; 00113 } 00114 else if (mark.getX() == m_field->getW() - 1 && 00115 isBorderDir(Dir::DIR_RIGHT)) 00116 { 00117 return Dir::DIR_RIGHT; 00118 } 00119 else if (mark.getY() == 0 && isBorderDir(Dir::DIR_UP)) { 00120 return Dir::DIR_UP; 00121 } 00122 else if (mark.getY() == m_field->getH() - 1 && 00123 isBorderDir(Dir::DIR_DOWN)) 00124 { 00125 return Dir::DIR_DOWN; 00126 } 00127 } 00128 00129 return Dir::DIR_NO; 00130 } 00131 //----------------------------------------------------------------- 00132 /** 00133 * Test whether there is only border in this direction. 00134 */ 00135 bool 00136 MarkMask::isBorderDir(Dir::eDir dir) const 00137 { 00138 bool result = false; 00139 Cube::t_models resist = getResist(dir); 00140 if (resist.size() == 1) { 00141 if (resist[0]->getIndex() == -1) { 00142 result = true; 00143 } 00144 } 00145 return result; 00146 } 00147