/** * Returns the quadrant of a directed line segment from p0 to p1. */ int Quadrant::quadrant(const Coordinate& p0, const Coordinate& p1) { double dx=p1.x-p0.x; double dy=p1.y-p0.y; if (dx==0.0 && dy==0.0) { throw util::IllegalArgumentException("Cannot compute the quadrant for two identical points " + p0.toString()); } return quadrant(dx, dy); }
/////////////////////////////////////////////////////////////////////////////// /// @brief Finds the shortest path from start to any target in the list, avoiding units and walls. A path will never be found if all targets are occupied or contains a wall. Returns true if and only if a path was found. /// /// @param path If the return value is true, path will contain the shortest path from start to the nearest target. /// @param start Where pathing is to start from. /// @param targetList A list of target destinations. /////////////////////////////////////////////////////////////////////////////// bool baseAI::findPath(vector<Coordinate>& path, const Coordinate start, const vector<Coordinate> targetList) { int dis[26][26]; int via[26][26]; bool success = false; bool changing = true; int newVal; static bool first = true; //via // 1 // 2 0 // 3 if (start.x() < 0 || start.y() < 0 || start.x() > 25 || start.y() > 25) { cout << "Error: Path was called with a start coordinate that was out of bounds."; return false; } for (int i = 0; i < targetList.size(); i++) { if (targetList[i].x() < 0 || targetList[i].y() < 0 || targetList[i].x() > 25 || targetList[i].y() > 25) { cout << "Error: Path was called with a target coordinate that was out of bounds."; return false; } } if (first) { first = false; plotWalls(); } plotUnits(); for (int x = 0; x < 26; x++) { for (int y = 0; y < 26; y++) { dis[x][y] = 999; via[x][y] = -1; } } for (int i = 0; i < targetList.size(); i++) { if (!occupied[targetList[i].x()][targetList[i].y()] && !walled[targetList[i].x()][targetList[i].y()]) dis[targetList[i].x()][targetList[i].y()] = 0; } while (changing) { changing = false; for (int x = 0; x < 26; x++) { for (int y = 0; y < 26; y++) { if (!walled[x][y] && (!occupied[x][y] || start == Coordinate(x,y))) { //newVal = dis[x][y]; if (x > 0) { if (dis[x-1][y]+1 < dis[x][y]) { dis[x][y] = dis[x-1][y]+1; via[x][y] = 2; changing = true; } } if (x < 25) { if (dis[x+1][y]+1 < dis[x][y]) { dis[x][y] = dis[x+1][y]+1; via[x][y] = 0; changing = true; } } if (y > 0) { if (dis[x][y-1]+1 < dis[x][y]) { dis[x][y] = dis[x][y-1]+1; via[x][y] = 3; changing = true; } } if (y < 25) { if (dis[x][y+1]+1 < dis[x][y]) { dis[x][y] = dis[x][y+1]+1; via[x][y] = 1; changing = true; } } } } } } path.clear(); Coordinate curPos(start.x(), start.y()); if (via[start.x()][start.y()] == -1) { success = false; } else { success = true; while (dis[curPos.x()][curPos.y()] != 0) { switch (via[curPos.x()][curPos.y()]) { case 0: curPos = curPos + Coordinate(1, 0); break; case 1: curPos = curPos + Coordinate(0, 1); break; case 2: curPos = curPos + Coordinate(-1, 0); break; case 3: curPos = curPos + Coordinate(0, -1); break; } path.push_back(curPos); } } return success; }
int main(int argc, char const *argv[]) { if (argc != 3 && argc != 4) { TERMINATE("%s\n%s\n%s\n%s\n", "Argumen tidak sesuai", "Cara kompilasi: g++ solver_checker.cpp -o solver_checker", "Cara pemakaian: ./solver_checker <file_input> <file_output> [<file_kamus>]", " Jika <file_kamus> tidak ada, maka akan digunakan \"kamus.txt\"."); } // Membuka berkas masukan dan keluaran FILE* fin = fopen(argv[1], "r"); if (fin == NULL) { TERMINATE("Berkas masukan \"%s\" tidak ditemukan!\n", argv[1]); } FILE* fout = fopen(argv[2], "r"); if (fout == NULL) { fclose(fin); TERMINATE("Berkas keluaran \"%s\" tidak ditemukan!\n", argv[2]); } if (argc == 4) { strcpy(buffer, argv[3]); } else { strcpy(buffer, DEFAULT_DICTIONARY_FILENAME); } FILE* fdict = fopen(buffer, "r"); if (fdict == NULL) { fclose(fin); fclose(fout); TERMINATE("Berkas kamus \"%s\" tidak ditemukan!\n", buffer); } // Membaca seluruh kata pada kamus dan memasukkannya ke set dictionary set<string> dictionary; while (fscanf(fdict, "%s", buffer) == 1) { toUppercaseWord(buffer); // Memastikan format sesuai ASSERT(consistsOfEnglishAlphabets(buffer), "Kata \"%s\" pada kamus tidak valid!\n", buffer); // Memastikan kata tidak muncul dua kali ASSERT(!EXIST(buffer, dictionary), "Kata \"%s\" muncul dua kali pada kamus\n", buffer); dictionary.insert(buffer); } fclose(fdict); // Membaca seluruh kata, koordinat dan arah pada masukan dan memasukkannya ke inputWords vector<CrosswordWord> inputWords; int row, col; while (fscanf(fin, "%s%d%d%s", buffer, &row, &col, bufferDirection) == 4) { toUppercaseWord(buffer); toUppercaseWord(bufferDirection); // Memastikan format sesuai ASSERT(consistsOfEnglishAlphabetsOrDots(buffer), "Kata \"%s\" pada masukan tidak valid!\n", buffer); ASSERT(!(strcmp(bufferDirection, "MENDATAR") && strcmp(bufferDirection, "MENURUN")), "Arah \"%s\" tidak valid! (Seharusnya \"mendatar\" atau \"menurun\")\n", bufferDirection); inputWords.push_back(CrosswordWord(buffer, CrosswordWord::getDirection(bufferDirection), row, col)); } fclose(fin); // Langsung berhenti saat masukan kosong ASSERT(!inputWords.empty(), "Tidak ada kata pada masukan!\n"); // Membaca seluruh kata, koordinat dan arah pada keluaran dan memasukkannya ke outputWords vector<CrosswordWord> outputWords; while (fscanf(fout, "%s%d%d%s", buffer, &row, &col, bufferDirection) == 4) { toUppercaseWord(buffer); toUppercaseWord(bufferDirection); // Memastikan format sesuai ASSERT(consistsOfEnglishAlphabets(buffer), "Kata \"%s\" pada keluaran tidak valid!\n", buffer); ASSERT(!(strcmp(bufferDirection, "MENDATAR") && strcmp(bufferDirection, "MENURUN")), "Arah \"%s\" tidak valid! (Seharusnya \"mendatar\" atau \"menurun\")\n", bufferDirection); outputWords.push_back(CrosswordWord(buffer, CrosswordWord::getDirection(bufferDirection), row, col)); } fclose(fout); // Langsung berhenti saat keluaran kosong ASSERT(!outputWords.empty(), "Tidak ada kata pada keluaran!\n"); // Memasukkan seluruh kata ke dalam grid yang direpresentasikan oleh map sambil mendaftar // semua kontradiksi yang ada pada grid map<Coordinate, char> crosswordGrid; map<Coordinate, CrosswordWord> directionMapping[2]; vector<Coordinate> contradictions; Coordinate topLeft, bottomRight; bool firstCharacter = true; for (vector<CrosswordWord>::iterator crosswordWord = inputWords.begin(); crosswordWord != inputWords.end(); ++crosswordWord) { Coordinate position = crosswordWord->start; // Periksa apakah sudah ada kata pada koordinat dan arah yang sama ASSERT(!EXIST(position, directionMapping[crosswordWord->direction]), "Ada dua kata pada koordinat (%d, %d) %s\n", position.row, position.col, crosswordWord->direction == ACCROSS ? "mendatar" : "menurun"); directionMapping[crosswordWord->direction][position] = *crosswordWord; // Masukkan tiap karakter ke map for (unsigned int i = 0; i < crosswordWord->word.length(); ++i) { char ch = crosswordWord->word[i]; if (EXIST(position, crosswordGrid)) { if (crosswordGrid[position] != ch) { crosswordGrid[position] = '?'; contradictions.push_back(position); } } else { crosswordGrid[position] = ch; } // Memperbarui batas crossword: topLeft dan bottomRight if (firstCharacter) { firstCharacter = false; topLeft = bottomRight = position; } else { if (position.row < topLeft.row) { topLeft.row = position.row; } if (position.col < topLeft.col) { topLeft.col = position.col; } if (position.row > bottomRight.row) { bottomRight.row = position.row; } if (position.col > bottomRight.col) { bottomRight.col = position.col; } } // Memajukan koordinat position sesuai dengan arah kata position.advance(crosswordWord->direction); } } // Cetak grid sebelum diisi printf("Teka-teki silang yang pada masukan:\n\n"); printCrossword(crosswordGrid); // Jika ada kontradiksi, keluarkan daftarnya if (!contradictions.empty()) { string message = "Terdapat kontradiksi pada koordinat"; for (int i = 0; i < contradictions.size(); ++i) { if (i == 0) { sprintf(buffer, " (%d, %d)", contradictions[i].row, contradictions[i].col); } else if (i + 1 < contradictions.size()) { sprintf(buffer, ", (%d, %d)", contradictions[i].row, contradictions[i].col); } else if (contradictions.size() == 2) { sprintf(buffer, " dan (%d, %d)", contradictions[i].row, contradictions[i].col); } else { sprintf(buffer, ", dan (%d, %d)", contradictions[i].row, contradictions[i].col); } message += buffer; } TERMINATE("%s\n", message.c_str()); } // Final check: cari kata baru yang terbentuk, atau cari kata yang tidak valid for (map<Coordinate, char>::iterator startIterator = crosswordGrid.begin(); startIterator != crosswordGrid.end(); ++startIterator) { Coordinate start = startIterator->first; for (int direction = 0; direction < 2; ++direction) { Coordinate position = start; string word; while (EXIST(position, crosswordGrid)) { word.push_back(crosswordGrid[position]); position.advance(direction); } Coordinate previous = start - Coordinate::STEP[direction]; // Periksa kalau pada koordinat dan arah ini ada kata pada map if (EXIST(start, directionMapping[direction])) { string originalWord = directionMapping[direction][start].word; // Kata tidak cocok ASSERT(word == originalWord, "Pada koordinat (%d, %d) %s: Seharusnya \"%s\", tapi ditemukan \"%s\"\n", start.row, start.col, direction == ACCROSS ? "mendatar" : "menurun", originalWord.c_str(), word.c_str()); // Kata diawali oleh huruf lain ASSERT(!EXIST(previous, crosswordGrid), "Ditemukan huruf sebelum kata \"%s\", (%d, %d) %s\n", originalWord.c_str(), start.row, start.col, direction == ACCROSS ? "mendatar" : "menurun"); } else { // Periksa kalau ada kata baru yang terbentuk ASSERT(EXIST(previous, crosswordGrid) || word.length() <= WORD_THRESHOLD, "Ditemukan kata \"%s\" yang tidak ada pada masukan pada (%d, %d) %s\n", word.c_str(), start.row, start.col, direction == ACCROSS ? "mendatar" : "menurun"); } } } // Sekarang, isi teka-teki silang tersebut dengan kata pada keluaran // Tiap kali ada kegagalan, simpan di issues. map<int, string> issues; set<string> usedWords; map<Coordinate, bool> finished[2]; int totalSuccess = 0; for (vector<CrosswordWord>::iterator crosswordWord = outputWords.begin(); crosswordWord != outputWords.end(); ++crosswordWord) { int i = crosswordWord - outputWords.begin(); Coordinate position = crosswordWord->start; // Kata tidak ada pada kamus if (!EXIST(crosswordWord->word, dictionary)) { sprintf(buffer, "Kata \"%s\" tidak ada pada kamus", crosswordWord->word.c_str()); issues[i] = buffer; continue; } // Kata yang sama telah dipakai if (EXIST(crosswordWord->word, usedWords)) { sprintf(buffer, "Kata \"%s\" telah digunakan sebelumnya", crosswordWord->word.c_str()); issues[i] = buffer; // issue ini diperbolehkan untuk lanjut } // Kata tidak ada pada directionMapping if (!EXIST(position, directionMapping[crosswordWord->direction])) { sprintf(buffer, "Tidak ada yang harus diisi pada (%d, %d) %s", position.row, position.col, crosswordWord->direction == ACCROSS ? "mendatar" : "menurun"); issues[i] = buffer; continue; } // Kata sudah diselesaikan sebelumnya if (finished[crosswordWord->direction][position]) { sprintf(buffer, "Kata pada (%d, %d) %s sudah diisi sebelumnya", position.row, position.col, crosswordWord->direction == ACCROSS ? "mendatar" : "menurun"); issues[i] = buffer; continue; } // Mencoba untuk mengisi kata pada posisi dan arah ini CrosswordWord unknown = directionMapping[crosswordWord->direction][position]; bool success = unknown.word.length() == crosswordWord->word.length(); for (int j = 0; j < unknown.word.length() && success; ++j) { if (unknown.word[j] != '.' && unknown.word[j] != crosswordWord->word[j]) { success = false; } } if (!success) { sprintf(buffer, "Kata \"%s\" tidak bisa diiisi pada (%d, %d) %s", crosswordWord->word.c_str(), position.row, position.col, crosswordWord->direction == ACCROSS ? "mendatar" : "menurun" ); issues[i] = buffer; continue; } // Berhasil! finished[crosswordWord->direction][position] = true; totalSuccess++; for (int j = 0; j < unknown.word.length() && success; ++j) { crosswordGrid[position] = crosswordWord->word[j]; position.advance(crosswordWord->direction); } } // Keluarkan hasilnya printf("Teka-teki silang setelah diisi:\n\n"); printCrossword(crosswordGrid); printf("Kata yang berhasil diisi : %d dari %d\n", totalSuccess, (int)inputWords.size()); if (!issues.empty()) { printf("Ditemukan %d masalah pada keluaran :\n", (int)issues.size()); for (map<int, string>::iterator it = issues.begin(); it != issues.end(); ++it) { printf("%3d. %s\n", it->first + 1, it->second.c_str()); } } return 0; }
inline int Coordinate::operator<(const Coordinate &rhs) const { if (x == rhs.GetX()) return y < rhs.GetY(); else return x < rhs.GetX(); }
void Coordinate::center(const Coordinate & coord){ const double centerx = (coord.getRelativeX1() + coord.getRelativeX2())/2; const double centery = (coord.getRelativeY1() + coord.getRelativeY2())/2; set(centerx, centery, centerx, centery); }
//This will return a list of polygons that can be used to explicitly //outline the bounding structure. This is being created for collision //debugging, and may not be appropriate for rendering complex arbitrary //hulls due to many redundant shared verticies. PtrLineList GetShape(){ //Create a wireframe for our AABB //Store the wires we've found PtrLineList result(new LineList); //We are finished when we run out of verticies to consider set<Coordinate> WorkingVerticies; set<Coordinate> WorkingVerticiesSwapBuffer; //add our first vertex as a seed WorkingVerticies.insert(Location); Coordinate CurrentV; Coordinate::iterator CVi; Coordinate PreviousV; //to iterate over our location and dimensions Coordinate::iterator Li; Coordinate::iterator Di; Line L; //When both vertex buffers are empty, we exit while(WorkingVerticies.size() > 0){ //When one vertex buffer is empty, we swap the new one in its place while(WorkingVerticies.size() > 0){ //(re)set our iterators Di = Dimensions.begin(); Li = Location.begin(); //begin processing the first vertex. CurrentV = PreviousV = *WorkingVerticies.begin(); CVi = CurrentV.begin(); //Go through our location dimension by dimension. while(CVi!=CurrentV.end()){ //if this dimension has not been incremented to its extreme if(*CVi == *Li){ //increment it to it's extreme *CVi = (*Li) + (*Di); //verticies in the swap buffer will be processed //in the next iterative pass. WorkingVerticiesSwapBuffer.insert(CurrentV); //Add our new line segment L.first = PreviousV; L.second = CurrentV; result->push_back(L); if(debug){ Coordinate::iterator Ci = PreviousV.begin(); while(Ci != PreviousV.end()){ ++Ci; } Ci = CurrentV.begin(); while(Ci != CurrentV.end()){ ++Ci; } } //Undo our increment and move on *CVi = *Li; } ++CVi; ++Li; ++Di; } //We are done processing this vertex. Remove it. WorkingVerticies.erase(WorkingVerticies.begin()); } //Dump swap buffer into WorkingVerticies. if swap.size()>0, we iterate. WorkingVerticies = WorkingVerticiesSwapBuffer; WorkingVerticiesSwapBuffer.clear(); } return result; }
inline Coordinate operator-(const Coordinate & coor, const Vector & vec) { return Coordinate(coor.getX() - vec.getDx(), coor.getY() - vec.getDy()); }
mapnik::geometry::point<double> geowave_featureset::create_point(Point point) { Coordinate coord = point.getCoordinate(); return mapnik::geometry::point<double>(coord.x(), coord.y()); }
Coordinate ClippingService::calcIntersection(Coordinate cord1, Coordinate cord2, ViewWindow *window, int regionCode) { double x, y; if (regionCode & TOP) { x = cord1.getx() + (cord2.getx() - cord1.getx()) * (window->getYwmax() - cord1.gety()) / (cord2.gety() - cord1.gety()); y = window->getYwmax(); } else if (regionCode & BOTTOM) { x = cord1.getx() + (cord2.getx() - cord1.getx()) * (window->getYwmin() - cord1.gety()) / (cord2.gety() - cord1.gety()); y = window->getYwmin(); } else if (regionCode & RIGHT) { y = cord1.gety() + (cord2.gety() - cord1.gety()) * (window->getXwmax() - cord1.getx()) / (cord2.getx() - cord1.getx()); x = window->getXwmax(); } else if (regionCode & LEFT) { y = cord1.gety() + (cord2.gety() - cord1.gety()) * (window->getXwmin() - cord1.getx()) / (cord2.getx() - cord1.getx()); x = window->getXwmin(); } return Coordinate(x, y); }
LatLon PlateCaree::crd2ll(const Coordinate &crd) const { LatLon ll(crd.y() * 180.0 / M_PI, crd.x() * 180.0 / M_PI); return ll; }
mapnik::geometry::polygon<double> geowave_featureset::create_polygon(Polygon polygon) { mapnik::geometry::polygon<double> polygon_out; // handle exterior ring { LineString geom = polygon.getExteriorRing(); mapnik::geometry::linear_ring<double> linear_ring; for (int point_idx = geom.getNumPoints()-1; point_idx >= 0; --point_idx) { Coordinate coord = geom.getPointN(point_idx).getCoordinate(); linear_ring.add_coord(coord.x(), coord.y()); } if (geom.isClosed()) { Coordinate coord = geom.getPointN(geom.getNumPoints()-1).getCoordinate(); linear_ring.add_coord(coord.x(), coord.y()); } polygon_out.set_exterior_ring(std::move(linear_ring)); } // handle interior rings { for (int ring_idx = 0; ring_idx < polygon.getNumInteriorRing(); ++ring_idx) { LineString geom = polygon.getInteriorRingN(ring_idx); mapnik::geometry::linear_ring<double> linear_ring; for (int point_idx = geom.getNumPoints()-1; point_idx >= 0; --point_idx) { Coordinate coord = geom.getPointN(point_idx).getCoordinate(); linear_ring.add_coord(coord.x(), coord.y()); } if (geom.isClosed()) { Coordinate coord = geom.getPointN(geom.getNumPoints()-1).getCoordinate(); linear_ring.add_coord(coord.x(), coord.y()); } polygon_out.add_hole(std::move(linear_ring)); } } return polygon_out; }
/** * @brief Applies registration of two points * * This method applies the registration of a left and right point set. The * points sets may only have the left point defined. This method determines * the valid geometry of the left point. If the right point is not defined, * it uses the left geometry to determine the right point to register the * left point with. If the right point is defined, it verifies the point has * valid geometry mapping in the right image. All points and geometry must * fall within the boundaries of the image and be valid or the point is * deemed invalid. * * Once the points is validated, registration is applied to the two points * using the left point as truth (or the pattern chip) and the right point * (search chip) is loaded according to the geometry of the left chip. An * affine transform is immediately applied in the Gruen algorithm to apply * the user supplied state of the affine and radiometric parameters. * * @author Kris Becker - 6/4/2011 * * @param lpg * @param rpg * @param affrad * * @return SmtkPoint */ SmtkPoint SmtkMatcher::Register(const PointGeometry &lpg, const PointGeometry &rpg, const AffineRadio &affrad) { // Validate object state validate(); // Test if the left point is defined. This will throw an error if this // situation occurs if (!lpg.getPoint().isValid()) { QString mess = "Left point is not defined which is required"; throw IException(IException::Programmer, mess, _FILEINFO_); } // First we need a lat,lon from the left image to find the same place in // the right image. Coordinate lpnt = lpg.getPoint(); Coordinate lgeom = lpg.getGeometry(); if (!lgeom.isValid()) { lgeom = getLatLon(lhCamera(), lpnt); } // Construct geometry and check validity PointGeometry left = PointGeometry(lpnt, lgeom); if (!left.isValid()) { m_offImage++; return ( SmtkPoint(PointPair(lpnt), PointPair(lgeom)) ); } // Validate the right point Coordinate rpnt = rpg.getPoint(); Coordinate rgeom = rpg.getGeometry(); if ( !rpnt.isValid() ) { if (rgeom.isValid()) { rpnt = getLineSample(rhCamera(), rgeom); } else { rpnt = getLineSample(rhCamera(), lgeom); rgeom = lgeom; } } else if (!rgeom.isValid() ){ rgeom = getLatLon(rhCamera(), rpnt); } // Construct and for good right geometry PointGeometry right = PointGeometry(rpnt, rgeom); if (!right.isValid()) { m_spiceErr++; return (SmtkPoint(PointPair(lpnt, rpnt), PointPair(lgeom, rgeom))); } try { // These calls are computationally expensive... can we fix it? m_gruen->PatternChip()->TackCube(lpnt.getSample(), lpnt.getLine()); m_gruen->PatternChip()->Load(*m_lhCube); m_gruen->SearchChip()->TackCube(rpnt.getSample(), rpnt.getLine()); m_gruen->SearchChip()->Load(*m_rhCube, *m_gruen->PatternChip(), *m_lhCube); } catch (IException &) { m_offImage++; // Failure to load is assumed an offimage error return (SmtkPoint(PointPair(lpnt,rpnt), PointPair(lgeom,rgeom))); } // Register the points with incoming affine/radiometric parameters m_gruen->setAffineRadio(affrad); return (makeRegisteredPoint(left, right, m_gruen.get())); }
Coordinate Coordinate::operator-(const Coordinate &other) const { return {this->x() - other.x(), this->y() - other.y()}; }
bool Piece::outOfBounds(Coordinate Coord) { if (Coord.getX() >= 0 && Coord.getX() <= 7 && Coord.getY() >= 0 && Coord.getY() <= 7) return false; return true; }
int main() { unsigned row, column, i; unsigned N_Losses, E_Losses; Coordinate* testSize; Coordinate* tempCoordinate; string testName1, testName2, loserName; Chooser* testChooser; Player* testNovice; Player* testExpert; Attack* testAttack; srand(time(NULL)); N_Losses = 0; E_Losses = 0; testName1 = "Pugwash"; testName2 = "Roger"; testSize = new Coordinate; testSize->init_SpecificCoordinate(10, 10); testChooser = new Random; for(i=0; i<1000; i++) { testNovice = new Novice(testSize, testName1); testExpert = new Expert(testSize, testName2); testNovice->setupFleet(); testExpert->setupFleet(); testNovice->addOpponent(testExpert); testExpert->addOpponent(testNovice); do { testAttack = testNovice->getAttack(); tempCoordinate = testAttack->getTargetCoordinate(); row = tempCoordinate->getCoordinateRow(); column = tempCoordinate->getCoordinateColumn(); cout << "Attack on " << testAttack->getTargetName() << " at row " << row << " column " << column << endl; testExpert->processAttack(testAttack); testNovice->setAttackResult(testAttack); if(testAttack->getFleetDestroyed() == false) { testAttack = testExpert->getAttack(); tempCoordinate = testAttack->getTargetCoordinate(); row = tempCoordinate->getCoordinateRow(); column = tempCoordinate->getCoordinateColumn(); cout << "Attack on " << testAttack->getTargetName() << " at row " << row << " column " << column << endl; testNovice->processAttack(testAttack); testExpert->setAttackResult(testAttack); } }while(testAttack->getFleetDestroyed() == false); loserName = testAttack->getTargetName(); if(loserName.compare(testName1) == 0) { N_Losses++; } else { E_Losses++; } cout << testAttack->getTargetName() << " has been defeated!" << endl; testAttack->uninit_Attack(); delete testAttack; delete testNovice; delete testExpert; } cout << testName1 << " lost " << N_Losses << " " << testName2 << " lost " << E_Losses << endl; cin.get(); }
void DimensionsTest::RunTests() { Coordinate zero; // [0]; zero.push_back(0); Coordinate one_two; // [1,2] one_two.push_back(1); one_two.push_back(2); Coordinate three_four; // [3,4] three_four.push_back(3); three_four.push_back(4); { // empty dimensions (unspecified) Dimensions d; TEST(d.isUnspecified()); TEST(d.isValid()); TEST(!d.isDontcare()); SHOULDFAIL(d.getCount()); SHOULDFAIL(d.getDimension(0)); TESTEQUAL("[unspecified]", d.toString()); SHOULDFAIL(d.getIndex(one_two)); SHOULDFAIL(d.getCount()); SHOULDFAIL(d.getDimension(0)); TESTEQUAL((unsigned int)0, d.getDimensionCount()); } { // dontcare dimensions [0] Dimensions d; d.push_back(0); TEST(!d.isUnspecified()); TEST(d.isDontcare()); TEST(d.isValid()); TESTEQUAL("[dontcare]", d.toString()); SHOULDFAIL(d.getIndex(zero)); SHOULDFAIL(d.getCount()); TESTEQUAL((unsigned int)0, d.getDimension(0)); TESTEQUAL((unsigned int)1, d.getDimensionCount()); } { // invalid dimensions Dimensions d; d.push_back(1); d.push_back(0); TEST(!d.isUnspecified()); TEST(!d.isDontcare()); TEST(!d.isValid()); TESTEQUAL("[1 0] (invalid)", d.toString()); SHOULDFAIL(d.getIndex(one_two)); SHOULDFAIL(d.getCount()); TESTEQUAL((unsigned int)1, d.getDimension(0)); TESTEQUAL((unsigned int)0, d.getDimension(1)); SHOULDFAIL(d.getDimension(2)); TESTEQUAL((unsigned int)2, d.getDimensionCount()); } { // valid dimensions [2,3] // two rows, three columns Dimensions d; d.push_back(2); d.push_back(3); TEST(!d.isUnspecified()); TEST(!d.isDontcare()); TEST(d.isValid()); TESTEQUAL("[2 3]", d.toString()); TESTEQUAL((unsigned int)2, d.getDimension(0)); TESTEQUAL((unsigned int)3, d.getDimension(1)); SHOULDFAIL(d.getDimension(2)); TESTEQUAL((unsigned int)6, d.getCount()); TESTEQUAL((unsigned int)5, d.getIndex(one_two)); TESTEQUAL((unsigned int)2, d.getDimensionCount()); } { //check a two dimensional matrix for proper x-major ordering std::vector<size_t> x; x.push_back(4); x.push_back(5); Dimensions d(x); size_t testDim1 = 4; size_t testDim2 = 5; for(size_t i = 0; i < testDim1; i++) { for(size_t j = 0; j < testDim2; j++) { Coordinate testCoordinate; testCoordinate.push_back(i); testCoordinate.push_back(j); TESTEQUAL(i+j*testDim1, d.getIndex(testCoordinate)); TESTEQUAL(vecToString(testCoordinate), vecToString(d.getCoordinate(i+j*testDim1))); } } } { //check a three dimensional matrix for proper x-major ordering std::vector<size_t> x; x.push_back(3); x.push_back(4); x.push_back(5); Dimensions d(x); size_t testDim1 = 3; size_t testDim2 = 4; size_t testDim3 = 5; for(size_t i = 0; i < testDim1; i++) { for(size_t j = 0; j < testDim2; j++) { for(size_t k = 0; k < testDim3; k++) { Coordinate testCoordinate; testCoordinate.push_back(i); testCoordinate.push_back(j); testCoordinate.push_back(k); TESTEQUAL(i + j*testDim1 + k*testDim1*testDim2, d.getIndex(testCoordinate)); TESTEQUAL(vecToString(testCoordinate), vecToString(d.getCoordinate(i + j*testDim1 + k*testDim1*testDim2))); } } } } { // alternate constructor std::vector<size_t> x; x.push_back(2); x.push_back(5); Dimensions d(x); TEST(!d.isUnspecified()); TEST(!d.isDontcare()); TEST(d.isValid()); TESTEQUAL((unsigned int)2, d.getDimension(0)); TESTEQUAL((unsigned int)5, d.getDimension(1)); SHOULDFAIL(d.getDimension(2)); TESTEQUAL((unsigned int)2, d.getDimensionCount()); } } // RunTests()
//when we call this, we must be sure the object is 3d void Draw3DQuads(){ Coordinate::iterator Di = Dimensions.begin(); Coordinate::iterator Li = Location.begin(); glBegin(GL_QUADS); //front glTexCoord2f(0.0,0.0); glVertex3f(Li[0]+Di[0],Li[1],Li[2]); glTexCoord2f(0.0,1.0); glVertex3f(Li[0]+Di[0],Li[1]+Di[1],Li[2]); glTexCoord2f(1.0,1.0); glVertex3f(Li[0],Li[1]+Di[1],Li[2]); glTexCoord2f(1.0,0.0); glVertex3f(Li[0],Li[1],Li[2]); //top glTexCoord2f(0.0,0.0); glVertex3f(Li[0],Li[1],Li[2]); glTexCoord2f(0.0,1.0); glVertex3f(Li[0]+Di[0],Li[1],Li[2]); glTexCoord2f(1.0,1.0); glVertex3f(Li[0]+Di[0],Li[1],Li[2]+Di[2]); glTexCoord2f(1.0,0.0); glVertex3f(Li[0],Li[1],Li[2]+Di[2]); //bottom glTexCoord2f(0.0,0.0); glVertex3f(Li[0],Li[1]+Di[1],Li[2]); glTexCoord2f(0.0,1.0); glVertex3f(Li[0]+Di[0],Li[1]+Di[1],Li[2]); glTexCoord2f(1.0,1.0); glVertex3f(Li[0]+Di[0],Li[1]+Di[1],Li[2]+Di[2]); glTexCoord2f(1.0,0.0); glVertex3f(Li[0],Li[1]+Di[1],Li[2]+Di[2]); //back glTexCoord2f(0.0,0.0); glVertex3f(Li[0],Li[1],Li[2]+Di[2]); glTexCoord2f(0.0,1.0); glVertex3f(Li[0]+Di[0],Li[1],Li[2]+Di[2]); glTexCoord2f(1.0,1.0); glVertex3f(Li[0]+Di[0],Li[1]+Di[1],Li[2]+Di[2]); glTexCoord2f(1.0,0.0); glVertex3f(Li[0],Li[1]+Di[1],Li[2]+Di[2]); //left glTexCoord2f(0.0,0.0); glVertex3f(Li[0],Li[1],Li[2]+Di[2]); glTexCoord2f(0.0,1.0); glVertex3f(Li[0],Li[1]+Di[1],Li[2]+Di[2]); glTexCoord2f(1.0,1.0); glVertex3f(Li[0],Li[1]+Di[1],Li[2]); glTexCoord2f(1.0,0.0); glVertex3f(Li[0],Li[1],Li[2]); //right glTexCoord2f(0.0,0.0); glVertex3f(Li[0]+Di[0],Li[1],Li[2]); glTexCoord2f(0.0,1.0); glVertex3f(Li[0]+Di[0],Li[1]+Di[1],Li[2]); glTexCoord2f(1.0,1.0); glVertex3f(Li[0]+Di[0],Li[1]+Di[1],Li[2]+Di[2]); glTexCoord2f(1.0,0.0); glVertex3f(Li[0]+Di[0],Li[1],Li[2]+Di[2]); glEnd(); }
int main(int argc, char const *argv[]) { if (argc != 3) { TERMINATE("%s\n%s\n%s\n", "Argumen tidak sesuai", "Cara kompilasi: g++ generator_checker.cpp -o generator_checker", "Cara pemakaian: ./generator_checker <file_input> <file_output>"); } // Membuka berkas masukan dan keluaran FILE* fin = fopen(argv[1], "r"); if (fin == NULL) { TERMINATE("Berkas masukan \"%s\" tidak ditemukan!\n", argv[1]); } FILE* fout = fopen(argv[2], "r"); if (fout == NULL) { fclose(fin); TERMINATE("Berkas keluaran \"%s\" tidak ditemukan!\n", argv[2]); } // Membaca seluruh kata pada berkas masukan dan memasukkannya ke inputWords set<string> inputWords; while (fscanf(fin, "%s", buffer) == 1) { toUppercaseWord(buffer); // Memastikan format sesuai ASSERT(consistsOfEnglishAlphabets(buffer), "Kata \"%s\" pada masukan tidak valid!\n", buffer); // Langsung keluar jika menemukan kata yang ada dua kali pada masukan if (EXIST(buffer, inputWords)) { fclose(fin); TERMINATE("Kata %s muncul dua kali pada masukan!\n", buffer); } inputWords.insert(buffer); } fclose(fin); // Membaca seluruh kata, koordinat dan arah pada keluaran dan memasukkannya ke outputWords vector<CrosswordWord> outputWords; set<string> exsistedOutputWords; int row, col; while (fscanf(fout, "%s%d%d%s", buffer, &row, &col, bufferDirection) == 4) { toUppercaseWord(buffer); toUppercaseWord(bufferDirection); // Memastikan format sesuai ASSERT(consistsOfEnglishAlphabets(buffer), "Kata \"%s\" pada keluaran tidak valid!\n", buffer); ASSERT(!(strcmp(bufferDirection, "MENDATAR") && strcmp(bufferDirection, "MENURUN")), "Arah \"%s\" tidak valid! (Seharusnya \"mendatar\" atau \"menurun\")\n", bufferDirection); // Langsung keluar jika menemukan kata yang tidak ada pada masukan, atau muncul dua kali // pada keluaran if (!EXIST(buffer, inputWords)) { fclose(fout); TERMINATE("Kata %s tidak ditemukan pada masukan!\n", buffer); } if (EXIST(buffer, exsistedOutputWords)) { fclose(fout); TERMINATE("Kata %s muncul dua kali pada keluaran!\n", buffer); } outputWords.push_back(CrosswordWord(buffer, CrosswordWord::getDirection(bufferDirection), row, col)); exsistedOutputWords.insert(buffer); } fclose(fout); // Langsung berhenti saat keluaran kosong ASSERT(!outputWords.empty(), "Tidak ada kata pada keluaran!\n"); // Memasukkan seluruh kata ke dalam grid yang direpresentasikan oleh map sambil mendaftar // semua kontradiksi yang ada pada grid map<Coordinate, char> crosswordGrid; map<Coordinate, CrosswordWord> directionMapping[2]; vector<Coordinate> contradictions; for (vector<CrosswordWord>::iterator crosswordWord = outputWords.begin(); crosswordWord != outputWords.end(); ++crosswordWord) { Coordinate position = crosswordWord->start; // Periksa apakah sudah ada kata pada koordinat dan arah yang sama ASSERT(!EXIST(position, directionMapping[crosswordWord->direction]), "Ada dua kata pada koordinat (%d, %d) %s\n", position.row, position.col, crosswordWord->direction == ACCROSS ? "mendatar" : "menurun"); directionMapping[crosswordWord->direction][position] = *crosswordWord; // Masukkan tiap karakter ke map for (unsigned int i = 0; i < crosswordWord->word.length(); ++i) { char ch = crosswordWord->word[i]; if (EXIST(position, crosswordGrid)) { if (crosswordGrid[position] != ch) { crosswordGrid[position] = '?'; contradictions.push_back(position); } } else { crosswordGrid[position] = ch; } // Memajukan koordinat position sesuai dengan arah kata position.advance(crosswordWord->direction); } } // Cetak grid printf("Teka-teki silang yang terbentuk:\n\n"); printCrossword(crosswordGrid); // Jika ada kontradiksi, keluarkan daftarnya if (!contradictions.empty()) { string message = "Terdapat kontradiksi pada koordinat"; for (int i = 0; i < contradictions.size(); ++i) { if (i == 0) { sprintf(buffer, " (%d, %d)", contradictions[i].row, contradictions[i].col); } else if (i + 1 < contradictions.size()) { sprintf(buffer, ", (%d, %d)", contradictions[i].row, contradictions[i].col); } else if (contradictions.size() == 2) { sprintf(buffer, " dan (%d, %d)", contradictions[i].row, contradictions[i].col); } else { sprintf(buffer, ", dan (%d, %d)", contradictions[i].row, contradictions[i].col); } message += buffer; } TERMINATE("%s\n", message.c_str()); } // Final check: cari kata baru yang terbentuk, atau cari kata yang tidak valid for (map<Coordinate, char>::iterator startIterator = crosswordGrid.begin(); startIterator != crosswordGrid.end(); ++startIterator) { Coordinate start = startIterator->first; for (int direction = 0; direction < 2; ++direction) { Coordinate position = start; string word; while (EXIST(position, crosswordGrid)) { word.push_back(crosswordGrid[position]); position.advance(direction); } Coordinate previous = start - Coordinate::STEP[direction]; // Periksa kalau pada koordinat dan arah ini ada kata pada map if (EXIST(start, directionMapping[direction])) { string originalWord = directionMapping[direction][start].word; // Kata tidak cocok ASSERT(word == originalWord, "Pada koordinat (%d, %d) %s: Seharusnya \"%s\", tapi ditemukan \"%s\"\n", start.row, start.col, direction == ACCROSS ? "mendatar" : "menurun", originalWord.c_str(), word.c_str()); // Kata diawali oleh huruf lain ASSERT(!EXIST(previous, crosswordGrid), "Ditemukan huruf sebelum kata \"%s\", (%d, %d) %s\n", originalWord.c_str(), start.row, start.col, direction == ACCROSS ? "mendatar" : "menurun"); } else { // Periksa kalau ada kata baru yang terbentuk ASSERT(EXIST(previous, crosswordGrid) || word.length() <= WORD_THRESHOLD, "Ditemukan kata \"%s\" yang tidak ada pada masukan pada (%d, %d) %s\n", word.c_str(), start.row, start.col, direction == ACCROSS ? "mendatar" : "menurun"); } } } // Setelah semua valid, keluarkan metrik penilaian printf("Teka-teki silang di atas valid!\n\n"); // Keluarkan banyak kata yang berhasil dipakai printf("1. Kata yang terpakai : %d dari %d\n", (int)outputWords.size(), (int)inputWords.size()); // Keluarkan "keterhubungan" dalam bentuk banyak komponen graf yang ada // Teknik flood-fill akan digunakan, dengan menggunakan struktur data stack int numComponent = 0; map<Coordinate, int> visited; for (map<Coordinate, char>::iterator startIterator = crosswordGrid.begin(); startIterator != crosswordGrid.end(); ++startIterator) { if (visited[startIterator->first]) { continue; } vector<Coordinate> stack; stack.push_back(startIterator->first); visited[stack.back()] = 1; while (!stack.empty()) { Coordinate top = stack.back(), temp; stack.pop_back(); temp = top - Coordinate::STEP[0]; if (!visited[temp] && EXIST(temp, crosswordGrid)) { stack.push_back(temp); visited[temp] = 1; } temp = top + Coordinate::STEP[0]; if (!visited[temp] && EXIST(temp, crosswordGrid)) { stack.push_back(temp); visited[temp] = 1; } temp = top - Coordinate::STEP[1]; if (!visited[temp] && EXIST(temp, crosswordGrid)) { stack.push_back(temp); visited[temp] = 1; } temp = top + Coordinate::STEP[1]; if (!visited[temp] && EXIST(temp, crosswordGrid)) { stack.push_back(temp); visited[temp] = 1; } } numComponent++; } printf("2. Komponen terhubung yang terbentuk : %d\n", numComponent); // Keluarkan ukuran teka-teki silang Coordinate topLeft, bottomRight; getCrosswordGridBounds(crosswordGrid, &topLeft, &bottomRight); printf("3. Ukuran teka-teki silang : %d baris x %d kolom = %d kotak\n", bottomRight.row - topLeft.row + 1, bottomRight.col - topLeft.col + 1, (bottomRight.row - topLeft.row + 1) * (bottomRight.col - topLeft.col + 1)); printf(" Banyak kotak yang terpakai : %d kotak\n", (int)crosswordGrid.size()); return 0; }
//========================================================================================================== // moment_arm = dl/dtheta, definition using inexact peturbation technique //========================================================================================================== double computeMomentArmFromDefinition(const SimTK::State &s, const GeometryPath &path, const Coordinate &coord) { using namespace SimTK; //Compute r = dl/dtheta SimTK::State s_ma = s; coord.setClamped(s_ma, false); coord.setLocked(s_ma, false); double theta = coord.getValue(s); double dtheta = 0.1*integ_accuracy; // Compute length 1 coord.setValue(s_ma, theta-dtheta, false); // satisfy contraints using project since we are close to the solution coord.getModel().getMultibodySystem().realize(s_ma, SimTK::Stage::Position); coord.getModel().getMultibodySystem().projectQ(s_ma, 1e-8); double theta1 = coord.getValue(s_ma); coord.getModel().getMultibodySystem().realize(s_ma, SimTK::Stage::Position); double len1 = path.getLength(s_ma); // Compute length 2 coord.setValue(s_ma, theta+dtheta, false); // satisfy contraints using project since we are close to the solution coord.getModel().getMultibodySystem().realize(s_ma, SimTK::Stage::Position); coord.getModel().getMultibodySystem().projectQ(s_ma, 1e-8); double theta2 = coord.getValue(s_ma); coord.getModel().getMultibodySystem().realize(s_ma, SimTK::Stage::Position); double len2 = path.getLength(s_ma); return (len1-len2)/(theta2-theta1); }
void KMLState::write(ostream& out, const Coordinate& c, double altitude) const { out << c.getLongitude().getAngle() << "," << c.getLatitude().getAngle() << "," << altitude; }
void Force::applyGeneralizedForce(const SimTK::State &s, const Coordinate &aCoord, double aForce, Vector &mobilityForces) const { _model->getMatterSubsystem().addInMobilityForce(s, SimTK::MobilizedBodyIndex(aCoord.getBodyIndex()), SimTK::MobilizerUIndex(aCoord.getMobilizerQIndex()), aForce, mobilityForces); }
double Ellipse::getEllipseAngle(const Coordinate& coord) const { Coordinate offset = coord - _center; Coordinate point = offset.rotate(-_majorP.angle()); return atan2(point.y() * _majorP.magnitude(), point.x() * _minorRadius); }
/********************************************************************************* Solve for moment arm, r = d(path_length)/d(theta) Ideally we want to compute r without perturbing theta values and recomputing lengths because it is inexact, very sensitive to perturbations that may cause a path (via) point to appear or disappear, and inefficient to recompute lengths, especially for complex paths involving wrapping. Refer to Moment-arm Theory document by Michael Sherman for details. **********************************************************************************/ double MomentArmSolver::solve(const State &s, const Coordinate &aCoord, const Array<PointForceDirection *> &pfds) { //const clock_t start = clock(); //Local modifiable copy of the state _stateCopy.updQ() = s.getQ(); _stateCopy.updU() = s.getU(); State& s_ma = _stateCopy; //const clock_t copyT = clock(); //cout << "MomentArmSolver::solve State copy time:" << 1000*(copyT-start)/CLOCKS_PER_SEC << "ms\n" <<endl; getModel().getMultibodySystem().realize(s_ma, SimTK::Stage::Instance); aCoord.setLocked(s_ma, false); double angle = aCoord.getValue(s_ma); //const clock_t init = clock(); //cout << "MomentArmSolver::solve realize instance in:" << 1000*(init-copyT)/CLOCKS_PER_SEC << "ms\n" <<endl; // Calculate coupling matrix C to determine the influence of other coordinates // (mobilities) on the coordinate of interest due to constraints s_ma.updU() = 0; // Light-up speed of coordinate of interest and see how other coordinates // affected by constraints respond aCoord.setSpeedValue(s_ma, 1); getModel().getMultibodySystem().realize(s_ma, SimTK::Stage::Velocity); // Satisfy all the velocity constraints. getModel().getMultibodySystem().projectU(s_ma, 1e-10); // Now calculate C. by checking how speeds of other coordinates change // normalized by how much the speed of the coordinate of interest changed _coupling = s_ma.getU() / aCoord.getSpeedValue(s_ma); //const clock_t computeC = clock(); //cout << "MomentArmSolver::solve compute C time:" << 1000*(computeC-init)/CLOCKS_PER_SEC << "ms\n" <<endl; angle = aCoord.getValue(s_ma); // Reset speeds to zero s_ma.updU() = 0; // Apply body forces along the geometry described by pfds due to a tension of 1N for(int i=0; i < pfds.getSize(); i++) { getModel().getMatterSubsystem().addInStationForce(s_ma, SimTK::MobilizedBodyIndex(pfds[i]->body().getIndex()), pfds[i]->point(), pfds[i]->direction(), _bodyForces); } // Convert body spatial forces F to equivalent mobility forces f based on // geometry (no dynamics required): f = ~J(q) * F. getModel().getMultibodySystem().getMatterSubsystem() .multiplyBySystemJacobianTranspose(s_ma, _bodyForces, _generalizedForces); //const clock_t torqueT = clock();; //cout << "MomentArmSolver::solve compute effective torque in:" << 1000*(torqueT-computeC)/CLOCKS_PER_SEC << "ms\n" <<endl; // Moment-arm is the effective torque (since tension is 1) at the // coordinate of interest taking into account the generalized forces also // acting on other coordinates that are coupled via constraint. return ~_coupling*_generalizedForces; }
//! [0] QDebug operator<<(QDebug dbg, const Coordinate &c) { dbg.nospace() << "(" << c.x() << ", " << c.y() << ")"; return dbg.space(); }
/////////////////////////////////////////////////////////////////////////////// /// @brief Queues an attack order for a unit. Reduces the unit's action count by 1 /// /// @param attackWith The unit that will attack /// @param attackCoord The location to attack /////////////////////////////////////////////////////////////////////////////// void baseAI::Attack(Unit& attackWith, const Coordinate& attackCoord) { sout.str(""); //Convert to s-expression sout << "(game-attack " << attackWith.id() << " " << attackCoord.x() << " " << attackCoord.y() << ")"; myOrder.s_expression = sout.str(); orders.push(myOrder); //Update unit actions attackWith.setActions(attackWith.actions()-1); attackWith.setMoves(0); //Update the official unit also for(unsigned int i=0; i < units.size(); ++i) { if(units[i].id() == attackWith.id()) { //Make sure we weren't given a reference to the unit in the unit list... if(&units[i] != &attackWith) { units[i].setActions(units[i].actions()-1); units[i].setMoves(0); } } } //Perform attack/heal on units at the location bool healed = false; for(unsigned int i=0; i < units.size(); i++) { if(units[i].location() == attackCoord) { //Friendly - Heal! if(units[i].owner() == me.id()) { healed = true; units[i].setCurHealth( units[i].curHealth() + attackWith.healPower()); } //Enemy unit - attack! else { units[i].setCurHealth( units[i].curHealth() - attackWith.attackPower()); } } } //If the unit didn't heal, he can splash if(!healed) { //Do splash! vector<Unit*> splashed; for(unsigned int i=0; i < units.size(); ++i) { //Find units within splash radius of 1, but not at attackCoord if(units[i].owner() != me.id() && units[i].distanceTo(attackCoord) == 1) { splashed.push_back(&units[i]); } } for(unsigned int i=0; i < splashed.size(); ++i) { //Damage the units that are splashed splashed[i]->setCurHealth( splashed[i]->curHealth() - attackWith.splashDamage()); } } return; }
bool equals(const Coordinate& p0, const Coordinate& p1, double distanceTolerance) { return p0.distance(p1) <= distanceTolerance; }
/**\brief Draws the Effect */ void Effect::Draw( void ) { Coordinate pos = GetWorldPosition(); visual->Draw( pos.GetScreenX(), pos.GetScreenY(), this->GetAngle()); }
Tile World::shortestPath(const Coordinate& target) { /* returns a "fake" Tile with data for shortest path from player to target */ if (target.level() < 0 || target.level() >= (int) _levels.size()) return Tile(); // outside map else if (target.level() == Saiph::position().level()) return _levels[Saiph::position().level()].tile(target); // target on same level int pivot = -1; int level_count = 1; int level_queue[_levels.size()]; level_queue[0] = Saiph::position().level(); bool level_added[_levels.size()]; for (int a = 0; a < (int) _levels.size(); ++a) level_added[a] = false; level_added[Saiph::position().level()] = true; Tile level_tile[_levels.size()]; level_tile[Saiph::position().level()] = shortestPath(Saiph::position()); Debug::pathing() << "Trying to find path to " << target << endl; while (++pivot < level_count) { /* check if target is on level */ if (level_queue[pivot] == target.level()) { Tile& tile = _levels[level_queue[pivot]].tile(target); if (tile.cost() == UNREACHABLE) continue; else if (tile.cost() == UNPASSABLE && tile.distance() > 1) continue; /* gotta modify this tile a bit since it's on another level */ level_tile[level_queue[pivot]].updatePath(level_tile[level_queue[pivot]].direction(), tile.distance() + level_tile[level_queue[pivot]].distance() + 1, tile.cost() + level_tile[level_queue[pivot]].cost() + 1); Debug::pathing() << "Found " << target << " " << level_tile[level_queue[pivot]].distance() << " tiles away, first checkpoint is " << level_tile[level_queue[pivot]].coordinate() << endl; return level_tile[level_queue[pivot]]; } /* path to upstairs on level */ for (map<Point, int>::const_iterator s = _levels[level_queue[pivot]].symbols((unsigned char) STAIRS_UP).begin(); s != _levels[level_queue[pivot]].symbols((unsigned char) STAIRS_UP).end(); ++s) { if (s->second == UNKNOWN_SYMBOL_VALUE) continue; // we don't know where these stairs lead else if (level_added[s->second]) continue; // already added this level Tile& tile = _levels[level_queue[pivot]].tile(s->first); if (tile.cost() >= UNPASSABLE) continue; Debug::pathing() << "Following upstairs on " << tile.coordinate() << " (" << _levels[level_queue[pivot]].name() << ") leading to level " << s->second << " (" << _levels[s->second].name() << ")" << endl; /* we know where these stairs lead, add the level to the queue */ level_added[s->second] = true; level_queue[level_count++] = s->second; if (pivot == 0) { /* pathing to upstairs on level we're standing on */ level_tile[s->second] = tile; if (tile.direction() == NOWHERE) level_tile[s->second].direction(UP); } else { /* pathing to upstairs on another level */ level_tile[s->second] = level_tile[level_queue[pivot]]; level_tile[s->second].updatePath(level_tile[s->second].direction(), level_tile[s->second].distance() + tile.distance() + 1, level_tile[s->second].cost() + tile.cost() + 1); } } /* path to downstairs on level */ for (map<Point, int>::const_iterator s = _levels[level_queue[pivot]].symbols((unsigned char) STAIRS_DOWN).begin(); s != _levels[level_queue[pivot]].symbols((unsigned char) STAIRS_DOWN).end(); ++s) { if (s->second == UNKNOWN_SYMBOL_VALUE) continue; // we don't know where these stairs lead else if (level_added[s->second]) continue; // already added this level Tile& tile = _levels[level_queue[pivot]].tile(s->first); if (tile.cost() >= UNPASSABLE) continue; Debug::pathing() << "Following downstairs on " << tile.coordinate() << " (" << _levels[level_queue[pivot]].name() << ") leading to level " << s->second << " (" << _levels[s->second].name() << ")" << endl; /* we know where these stairs lead, add the level to the queue */ level_added[s->second] = true; level_queue[level_count++] = s->second; if (pivot == 0) { /* pathing to downstairs on level we're standing on */ level_tile[s->second] = tile; if (tile.direction() == NOWHERE) level_tile[s->second].direction(DOWN); } else { /* pathing to downstairs on another level */ level_tile[s->second] = level_tile[level_queue[pivot]]; level_tile[s->second].updatePath(level_tile[s->second].direction(), level_tile[s->second].distance() + tile.distance() + 1, level_tile[s->second].cost() + tile.cost() + 1); } } /* path to portals on level */ for (map<Point, int>::const_iterator s = _levels[level_queue[pivot]].symbols((unsigned char) MAGIC_PORTAL).begin(); s != _levels[level_queue[pivot]].symbols((unsigned char) MAGIC_PORTAL).end(); ++s) { if (s->second == UNKNOWN_SYMBOL_VALUE) continue; // we don't know where this portal leads else if (level_added[s->second]) continue; // already added this level Tile& tile = _levels[level_queue[pivot]].tile(s->first); if (tile.cost() >= UNPASSABLE) continue; Debug::info() << "Following magic portal on " << tile.coordinate() << " (" << _levels[level_queue[pivot]].name() << ") leading to level " << s->second << " (" << _levels[s->second].name() << ")" << endl; /* we know where this portal leads, add the level to the queue */ level_added[s->second] = true; level_queue[level_count++] = s->second; if (pivot == 0) { /* pathing to portal on level we're standing on */ level_tile[s->second] = tile; if (tile.direction() == NOWHERE) level_tile[s->second].direction(DOWN); } else { /* pathing to portal on another level */ level_tile[s->second] = level_tile[level_queue[pivot]]; level_tile[s->second].updatePath(level_tile[s->second].direction(), level_tile[s->second].distance() + tile.distance() + 1, level_tile[s->second].cost() + tile.cost() + 1); } } } return Tile(); // symbol not found }
/* * Das ist die Standart Bresenham-Algorithmus. * Die Lage der Punkte wird nicht geprüft, sondern davon ausgegangen, dass dies schon passiert ist. * Die Angabe des Orthanden und der Basis dient der Translation der Koordinaten. */ void PrimitiveLine::DrawLineBresenham(ImageBase *img, const Coordinate &to,const char orthant, const Coordinate &offset) const { int deltaX = to.GetX(); int deltaY = to.GetY(); int e= 2*deltaY - deltaX; int x = 0; int y = 0; Coordinate coord; while( x <= deltaX ){ /* Ruecktransformation der Koordinaten */ coord = DrawLineTranslateCoordinates(offset,x,y,orthant); /* Pixel zeichnen (wenn Koordinaten im Bild) */ if(coord.GetX() >= 0 && (unsigned)coord.GetX() < img->GetWidth() && coord.GetY() >= 0 && (unsigned)coord.GetY() < img->GetHeight()) { img->SetPixel(coord.GetX(),coord.GetY(),0,GetColor().GetR()); img->SetPixel(coord.GetX(),coord.GetY(),1,GetColor().GetG()); img->SetPixel(coord.GetX(),coord.GetY(),2,GetColor().GetB()); } /* Gemaess Bresenham-Algorithmus bestimmen, ob das Pixel rechts vom * vorigen Pixel oder rechtsoben vom vorigen Pixel gesetzt werden muss */ if( e > 0 ){ y++; e += 2*(deltaY - deltaX); }else{ e += 2*deltaY; } x++; } }
/* public static */ int Quadrant::quadrant(const Coordinate& p0, const Coordinate& p1) { if (p1.x == p0.x && p1.y == p0.y) { throw util::IllegalArgumentException("Cannot compute the quadrant for two identical points " + p0.toString()); } if (p1.x >= p0.x) { if (p1.y >= p0.y) return NE; else return SE; } else { if (p1.y >= p0.y) return NW; else return SW; } }