int Arena::getNumberOfVisitedCells(Maze& m) { int count = 0; //for each cell in the maze for (int i = 0; i < m.getRows(); i++) { for (int j = 0; j < m.getCols(); j++) { //if cell has been visited, increase count if (m.getCell(i,j)->isVisited()) count++; } } return count; }
double Arena::runSimulation(Maze& maze, Robot& r) { //reset maze maze.clearVisited(); maze.clearValues(); //set needed values after reset Cell* curCell = maze.getStartCell(); robotOrientation = direction::SOUTH; unsigned int move; double score; //while the robot is not in the same cell facing the same direction while (!repeat(robotOrientation, curCell->getValue()) && !(curCell == maze.getEndCell())) { //set current cell to visited and update it's value curCell->setVisited(); curCell->setValue(curCell->getValue() + robotOrientation); //send the robot the environment and get it's next move move = r.getMove(getEnv(robotOrientation, curCell)); //perform next move //find rotation if (move == 3 || move == 7) { robotOrientation = Direction::left(robotOrientation); } else if (move == 2 || move == 6) { robotOrientation = Direction::opposite(robotOrientation); } else if (move == 1 || move == 5) { robotOrientation = Direction::right(robotOrientation); } else { //no rotation } //move forwards if (!curCell->hasWall(robotOrientation) && !curCell->hasEdge(robotOrientation)) { curCell = maze.getCell(curCell->getRow() + Direction::row(robotOrientation), curCell->getCol() + Direction::col(robotOrientation)); } } //calculate score //score is a 1 if the end has been reached, else it is 1 - (distance from end * 0.01) if (curCell == maze.getEndCell()) { score = 1.0; } else { score = (double)getNumberOfVisitedCells(maze) / (double)((double)maze.getRows() * (double)maze.getCols()); } //return score return score; }
void FindPathsFromXtoY::findAllThePaths(Maze& mazeT, Cell* startC, Cell* finalC) { currentPath.pathVec.push_back(startC); currentPath.sizeOfPath++; startC->isCovered = true; if(startC->row == finalC->row && startC->col == finalC->col) { allThePaths.push_back(currentPath); /*std::cout << "Current situation: " << std::endl; printAllThePaths();*/ // currentPath.clear(); // currentPath.pathVec.push_back(startCell); return; } for(int i = 0; i < 4; i++) { if(startC->row + xMoves[i] >= 0 && startC->row + xMoves[i] < mazeT.getRows() && startC->col + yMoves[i] >=0 && startC->col + yMoves[i] < mazeT.getCols()) { Cell* stepCell = mazeT.getCell(startC->row + xMoves[i], startC->col + yMoves[i]); if(stepCell && stepCell->isCovered == false && stepCell->isOkayToPass()) { // currentPath.push_back(stepCell); findAllThePaths(mazeT,stepCell,finalC); currentPath.pathVec.pop_back(); currentPath.sizeOfPath--; stepCell->isCovered = false; } } } // startC->isCovered = false; }
bool Computer::move_to_hero(Maze& level_map) { Point lu_cornor; Point rd_cornor; Point point; unsigned step = 1; Point hero_position = position; unsigned hero_review = review; bool end = false; unsigned ** screen; unsigned size_screen = (review * 2 + 1); screen = new unsigned*[size_screen]; for (auto i = 0U; i < size_screen; ++i) screen[i] = new unsigned[size_screen]; for (auto i = 0U; i < size_screen; ++i) for (auto j = 0U; j < size_screen; ++j) screen[i][j] = 0; screen[hero_review][hero_review] = 1; while (step <= hero_review) { lu_cornor.x = hero_position.x - (step-1); lu_cornor.y = hero_position.y - (step-1); rd_cornor.x = hero_position.x + (step-1); rd_cornor.y = hero_position.y + (step-1); for (int i = lu_cornor.y; i <= rd_cornor.y; i++) for (int j = lu_cornor.x; j <= rd_cornor.x; j++) { if (!level_map.isExistance(i, j)) continue; point.y = i - hero_position.y + hero_review; point.x = j - hero_position.x + hero_review; if (screen[point.y][point.x] == step && level_map.getCell(i, j) != '#') { if (level_map.isExistance(i - 1, j) && (point.y - 1 >= 0)) if (screen[point.y - 1][point.x] == 0) screen[point.y - 1][point.x] = step + 1; if (level_map.isExistance(i + 1, j) && ((unsigned)point.y + 1 < size_screen)) if (screen[point.y + 1][point.x] == 0) screen[point.y + 1][point.x] = step + 1; if (level_map.isExistance(i, j - 1) && (point.x - 1 >= 0)) if (screen[point.y][point.x - 1] == 0) screen[point.y][point.x - 1] = step + 1; if (level_map.isExistance(i, j + 1) && ((unsigned)point.x + 1 < size_screen)) if (screen[point.y][point.x + 1] == 0) screen[point.y][point.x + 1] = step + 1; } } step++; } for (auto i = 0U; i < size_screen; ++i) { for (auto j = 0U; j < size_screen; ++j) { if (screen[i][j] != 0 && level_map.getCell(i + position.y - review, j + position.x - review) == 'H') { point.y = i; point.x = j; for (auto it = screen[i][j] - 1; it > 1; --it) { if ((unsigned)point.x + 1 < size_screen) if (screen[point.y][point.x + 1] == it && level_map.getCell(point.y + position.y - review, point.x + 1 + position.x - review) != '#') { point.x = point.x + 1; point.y = point.y; continue; } if (point.x - 1 >= 0) if (screen[point.y][point.x - 1] == it && level_map.getCell(point.y + position.y - review, point.x - 1 + position.x - review) != '#') { point.x = point.x - 1; point.y = point.y; continue; } if ((unsigned)point.y + 1 < size_screen) if (screen[point.y + 1][point.x] == it && level_map.getCell(point.y + 1 + position.y - review, point.x + position.x - review) != '#') { point.x = point.x; point.y = point.y + 1; continue; } if (point.y - 1 >= 0) if (screen[point.y - 1][point.x] == it && level_map.getCell(point.y - 1 + position.y - review, point.x + position.x - review) != '#') { point.x = point.x; point.y = point.y - 1; continue; } } end = true; break; } } if (end) break; } if (end) { prev_position = position; position.x = position.x + point.x - review; position.y = position.y + point.y - review; } delete [] screen; if (end) return true; else return false; }
bool Computer::movement(Maze level_map) { const auto Q_POSSIBILITIES = 4U; SegmentDistribution distributed_move[Q_POSSIBILITIES]; Point shift; Point temp; bool result, approval1 = false, approval2 = false, approval3 = false; unsigned left_boundary = 0; unsigned root_decision, decision; if(move_to_hero(level_map) == true) return true; //относительно героя компьютера if (prev_position == position) { shift.x = 0; shift.y = -1; } else { shift.x = position.x - prev_position.x; shift.y = position.y - prev_position.y; } distributed_move[0].probability = 70; // Смещение вперёд distributed_move[0].shift = shift; distributed_move[1].probability = 2; // Смещение назад distributed_move[1].shift.x = -shift.x; distributed_move[1].shift.y = -shift.y; distributed_move[2].probability = 14; // Смещение влево distributed_move[2].shift.x = shift.y; distributed_move[2].shift.y = -shift.x; distributed_move[3].probability = 14; // Смещение вправо distributed_move[3].shift.x = -shift.y; distributed_move[3].shift.y = shift.x; for (auto i = 0U; i < Q_POSSIBILITIES; ++i) { temp.x = position.x + distributed_move[i].shift.x; temp.y = position.y + distributed_move[i].shift.y; if (level_map.isExistance(temp.y, temp.x)) { approval1 = level_map.getCell(temp.y, temp.x) != '#'; approval2 = level_map.getCell(temp.y, temp.x) != 'E'; approval3 = level_map.getCell(temp.y, temp.x) != 'M'; } result = approval1 && approval2 && approval3; distributed_move[i].use = result; if (result == true) left_boundary += distributed_move[i].probability; } if (left_boundary == 0) return true; root_decision = rand() % left_boundary; for (auto i = 0U; i < Q_POSSIBILITIES; ++i) { if (!distributed_move[i].use) continue; if (root_decision < distributed_move[i].probability) { decision = i; break; } else root_decision -= distributed_move[i].probability; } prev_position = position; position.x += distributed_move[decision].shift.x; position.y += distributed_move[decision].shift.y; return true; }
double Arena::runSimulation(Maze& maze, Robot& r, sf::RenderWindow& window) { sf::Font f; if (!f.loadFromFile("fonts/Oswald-Regular.ttf")) return 0; const int ROWS = maze.getRows(); const int COLS = maze.getCols(); const int CELL_SIZE = 30, OFFSET = 150; sf::RectangleShape rectangles[10][10]; vector<sf::RectangleShape> lines; //text for display of info sf::Text bst; sf::Text med; sf::Text gen; //set fonts bst.setFont(f); med.setFont(f); gen.setFont(f); bst.setColor(sf::Color::Black); med.setColor(sf::Color::Black); gen.setColor(sf::Color::Black); //set sizes bst.setCharacterSize(24); med.setCharacterSize(24); gen.setCharacterSize(24); //set positions gen.setPosition(10, 10); bst.setPosition(10, 40); med.setPosition(10, 70); //set strings stringstream stream; stream.str(""); string out; stream << generation; stream >> out; out = "Generation: " + out; gen.setString(out); stream.str(string()); stream.clear(); out.clear(); stream << setprecision(2) << median; stream >> out; out = "Median Score: " + out; med.setString(out); stream.str(string()); stream.clear(); out.clear(); stream << setprecision(2) << best; stream >> out; out = "Best Score: " + out; bst.setString(out); //Cell used to find borders for the board spaces Cell* c; //populate rectangles as board spaces for (int i = 0; i < ROWS; i++) { for (int j = 0; j < COLS; j++) { //add board spaces, set color and position rectangles[i][j] = sf::RectangleShape(sf::Vector2f(CELL_SIZE, CELL_SIZE)); rectangles[i][j].setFillColor(sf::Color::White); rectangles[i][j].setPosition((j * CELL_SIZE) + OFFSET, (i * CELL_SIZE) + OFFSET); //set cell to find borders and highlight end cell c = maze.getCell(i, j); if (c == maze.getEndCell()) rectangles[i][j].setFillColor(sf::Color::Blue); if (c->hasWall(direction::NORTH) || c->hasEdge(direction::NORTH)) { lines.push_back(sf::RectangleShape(sf::Vector2f(CELL_SIZE, 2))); lines[lines.size() - 1].setPosition(rectangles[i][j].getPosition()); lines[lines.size() - 1].setFillColor(sf::Color::Black); } if (c->hasWall(direction::WEST) || c->hasEdge(direction::WEST)) { lines.push_back(sf::RectangleShape(sf::Vector2f(2, CELL_SIZE))); lines[lines.size() - 1].setPosition(rectangles[i][j].getPosition()); lines[lines.size() - 1].setFillColor(sf::Color::Black); } if (c->hasWall(direction::SOUTH) || c->hasEdge(direction::SOUTH)) { lines.push_back(sf::RectangleShape(sf::Vector2f(CELL_SIZE, 2))); lines[lines.size() - 1].setPosition(rectangles[i][j].getPosition() + sf::Vector2f(0, CELL_SIZE)); lines[lines.size() - 1].setFillColor(sf::Color::Black); } if (c->hasWall(direction::EAST) || c->hasEdge(direction::EAST)) { lines.push_back(sf::RectangleShape(sf::Vector2f(2, CELL_SIZE))); lines[lines.size() - 1].setPosition(rectangles[i][j].getPosition() + sf::Vector2f(CELL_SIZE, 0)); lines[lines.size() - 1].setFillColor(sf::Color::Black); } } } //reset maze maze.clearVisited(); maze.clearValues(); //set needed values after reset Cell* curCell = maze.getStartCell(); robotOrientation = direction::SOUTH; unsigned int move; double score; //clock for delays sf::Clock clock; sf::Time delay = sf::milliseconds(50); //DRAW WINDOW INITIALLY WITH START CELL HIGHLIGHTED AS CURRENT window.clear(sf::Color::White); //highlight start cell rectangles[curCell->getRow()][curCell->getCol()].setFillColor(sf::Color::Green); //add cells for (int i = 0; i < ROWS; i++) { for (int j = 0; j < COLS; j++) { window.draw(rectangles[i][j]); } } //add borders for (unsigned int i = 0; i < lines.size(); i++) { window.draw(lines[i]); } //add information window.draw(gen); window.draw(bst); window.draw(med); window.display(); //while the robot is not in the same cell facing the same direction while (!repeat(robotOrientation, curCell->getValue()) && !(curCell == maze.getEndCell())) { //set current cell to visited and update it's value curCell->setVisited(); curCell->setValue(curCell->getValue() + robotOrientation); //send the robot the environment and get it's next move move = r.getMove(getEnv(robotOrientation, curCell)); //perform next move //find rotation if (move == 3 || move == 7) { robotOrientation = Direction::left(robotOrientation); } else if (move == 2 || move == 6) { robotOrientation = Direction::opposite(robotOrientation); } else if (move == 1 || move == 5) { robotOrientation = Direction::right(robotOrientation); } else { //no rotation } //reset clock and hold for display clock.restart(); while (clock.getElapsedTime() < delay) {} //HIGHLIGHT CURRENT CELL AS VISITED rectangles[curCell->getRow()][curCell->getCol()].setFillColor(sf::Color::Red); //move forwards if (!curCell->hasWall(robotOrientation) && !curCell->hasEdge(robotOrientation)) { curCell = maze.getCell(curCell->getRow() + Direction::row(robotOrientation), curCell->getCol() + Direction::col(robotOrientation)); } //REDRAW WINDOW WITH UPDATED CELLS window.clear(sf::Color::White); //highlight current visiting cell rectangles[curCell->getRow()][curCell->getCol()].setFillColor(sf::Color::Green); //add cells for (int i = 0; i < ROWS; i++) { for (int j = 0; j < COLS; j++) { window.draw(rectangles[i][j]); } } //add borders for (unsigned int i = 0; i < lines.size(); i++) { window.draw(lines[i]); } sf::Event event; while (window.pollEvent(event)) { // "close requested" event: we close the window if (event.type == sf::Event::Closed) return -1; } //add information window.draw(gen); window.draw(bst); window.draw(med); window.display(); } //calculate score //score is a 1 if the end has been reached, else it is 1 - (distance from end * 0.01) if (curCell == maze.getEndCell()) { score = 1.0; } else { score = (double)getNumberOfVisitedCells(maze) / (double)((double)maze.getRows() * (double)maze.getCols()); } //reset clock and hold for display clock.restart(); while (clock.getElapsedTime() < sf::milliseconds(1000)) {} //return score return score; }