Func repeat_edge(const Func &source, const std::vector<std::pair<Expr, Expr>> &bounds) { std::vector<Var> args(source.args()); user_assert(args.size() >= bounds.size()) << "repeat_edge called with more bounds (" << bounds.size() << ") than dimensions (" << args.size() << ") Func " << source.name() << "has.\n"; std::vector<Expr> actuals; for (size_t i = 0; i < bounds.size(); i++) { Var arg_var = args[i]; Expr min = bounds[i].first; Expr extent = bounds[i].second; if (min.defined() && extent.defined()) { actuals.push_back(clamp(likely(arg_var), min, min + extent - 1)); } else if (!min.defined() && !extent.defined()) { actuals.push_back(arg_var); } else { user_error << "Partially undefined bounds for dimension " << arg_var << " of Func " << source.name() << "\n"; } } // If there were fewer bounds than dimensions, regard the ones at the end as unbounded. actuals.insert(actuals.end(), args.begin() + actuals.size(), args.end()); Func bounded("repeat_edge"); bounded(args) = source(actuals); return bounded; }
/** * Set the minimum area based on the given size */ void MythUIType::SetMinArea(const QSize &size) { // If a minsize is not set, don't use MinArea if (m_MinSize.x() < 1) return; /** * The MinArea will have the same origin as the normal Area, * but can have a smaller size. */ QSize minsize = QSize(m_MinSize.x(), m_MinSize.y()); QSize bounded(size); bounded = bounded.expandedTo(minsize); bounded = bounded.boundedTo(m_Area.size()); if (bounded == m_MinArea.size()) return; m_MinArea.setSize(bounded); m_MinArea.setX(m_Area.x()); m_MinArea.setY(m_Area.y()); if (m_Parent) m_Parent->SetMinAreaSiblings(bounded, bounded.width() - m_Area.width(), bounded.height() - m_Area.height()); }
void ArchiveReader::read_everything(read_everything_co_t::push_type &sink){ if (!this->version_manifest) this->read_manifest(); auto ptr = this->get_stream(); auto file_data_start = this->keypair ? 4096 / 8 : 0; ptr->seekg(file_data_start); boost::iostreams::stream<BoundedInputFilter> bounded(*ptr, this->base_objects_offset - file_data_start); std::istream *stream = &bounded; std::shared_ptr<std::istream> crypto; if (this->keypair){ CryptoPP::SecByteBlock key, iv; zekvok_assert(this->get_key_iv(key, iv, KeyIndices::FileDataKey)); crypto = CryptoInputFilter::create(default_crypto_algorithm, *stream, &key, &iv); stream = crypto.get(); } boost::iostreams::stream<LzmaInputFilter> lzma(*stream); zekvok_assert(this->stream_ids.size() == this->stream_sizes.size()); for (size_t i = 0; i < this->stream_ids.size(); i++){ boost::iostreams::stream<BoundedInputFilter> bounded2(lzma, this->stream_sizes[i]); sink(std::make_pair(this->stream_ids[i], &bounded2)); //Discard left over bytes. boost::iostreams::stream<NullOutputStream> null(0); null << bounded2.rdbuf(); } }
bool BackupSystem::verify(version_number_t version) const{ if (!this->version_exists(version)) return false; fs::ifstream file(this->get_version_path(version), std::ios::binary); if (!file) return false; file.seekg(0, std::ios::end); std::uint64_t size = file.tellg(); sha256_digest digest; file.seekg(-(int)digest.size(), std::ios::end); file.read((char *)digest.data(), digest.size()); if (file.gcount() != digest.size()) return false; file.seekg(0); sha256_digest new_digest; { boost::iostreams::stream<BoundedInputFilter> bounded(file, size - digest.size()); boost::iostreams::stream<HashInputFilter> hash(bounded, new CryptoPP::SHA256); { boost::iostreams::stream<NullOutputStream> output(0); output << hash.rdbuf(); } hash->get_result(new_digest.data(), new_digest.size()); } return new_digest == digest; }
std::shared_ptr<VersionManifest> ArchiveReader::read_manifest(){ auto stream = this->get_stream(); if (this->manifest_offset < 0){ const int uint64_length = sizeof(std::uint64_t); std::int64_t start = -uint64_length - sha256_digest_length; stream->seekg(start, std::ios::end); char temp[uint64_length]; stream->read(temp, uint64_length); if (stream->gcount() != uint64_length) throw ArchiveReadException("Invalid data: File is too small to possibly be valid"); deserialize_fixed_le_int(this->manifest_size, temp); start -= this->manifest_size; stream->seekg(start, std::ios::end); this->manifest_offset = stream->tellg(); }else stream->seekg(this->manifest_offset); { boost::iostreams::stream<BoundedInputFilter> bounded(*stream, this->manifest_size); boost::iostreams::stream<LzmaInputFilter> lzma(bounded); ImplementedDeserializerStream ds(lzma); this->version_manifest.reset(ds.begin_deserialization<VersionManifest>(config::include_typehashes)); if (!this->version_manifest) throw ArchiveReadException("Invalid data: Error during manifest deserialization"); } this->base_objects_offset = this->manifest_offset - this->version_manifest->archive_metadata.entries_size_in_archive; this->stream_ids = this->version_manifest->archive_metadata.stream_ids; this->stream_sizes = this->version_manifest->archive_metadata.stream_sizes; return this->version_manifest; }
std::vector<std::shared_ptr<FileSystemObject>> ArchiveReader::read_base_objects(){ if (!this->version_manifest) this->read_manifest(); zekvok_assert(this->version_manifest); decltype(this->base_objects) ret; ret.reserve(this->version_manifest->archive_metadata.entry_sizes.size()); auto stream = this->get_stream(); stream->seekg(this->base_objects_offset); { boost::iostreams::stream<BoundedInputFilter> bounded(*stream, this->manifest_offset - this->base_objects_offset); std::istream *stream = &bounded; std::shared_ptr<std::istream> crypto; if (this->keypair){ CryptoPP::SecByteBlock key, iv; zekvok_assert(this->get_key_iv(key, iv, KeyIndices::FileObjectDataKey)); crypto = CryptoInputFilter::create(default_crypto_algorithm, *stream, &key, &iv); stream = crypto.get(); } boost::iostreams::stream<LzmaInputFilter> lzma(*stream); for (const auto &s : this->version_manifest->archive_metadata.entry_sizes){ boost::iostreams::stream<BoundedInputFilter> bounded2(lzma, s); ImplementedDeserializerStream ds(bounded2); std::shared_ptr<FileSystemObject> fso(ds.begin_deserialization<FileSystemObject>(config::include_typehashes)); if (!fso) throw ArchiveReadException("Invalid data: Error during FSO deserialization"); ret.push_back(fso); } } this->base_objects = std::move(ret); return this->base_objects; }
Func mirror_interior(const Func &source, const std::vector<std::pair<Expr, Expr>> &bounds) { std::vector<Var> args(source.args()); user_assert(args.size() >= bounds.size()) << "mirror_interior called with more bounds (" << bounds.size() << ") than dimensions (" << args.size() << ") Func " << source.name() << "has.\n"; std::vector<Expr> actuals; for (size_t i = 0; i < bounds.size(); i++) { Var arg_var = args[i]; Expr min = bounds[i].first; Expr extent = bounds[i].second; if (min.defined() && extent.defined()) { Expr limit = extent - 1; Expr coord = arg_var - min; // Enforce zero origin. coord = coord % (2 * limit); // Range is 0 to 2w-1 coord = coord - limit; // Range is -w, w coord = abs(coord); // Range is 0, w coord = limit - coord; // Range is 0, w coord = coord + min; // Restore correct min // The boundary condition probably doesn't apply coord = select(arg_var < min || arg_var >= min + extent, coord, clamp(likely(arg_var), min, min + extent - 1)); actuals.push_back(coord); } else if (!min.defined() && !extent.defined()) { actuals.push_back(arg_var); } else { user_error << "Partially undefined bounds for dimension " << arg_var << " of Func " << source.name() << "\n"; } } // If there were fewer bounds than dimensions, regard the ones at the end as unbounded. actuals.insert(actuals.end(), args.begin() + actuals.size(), args.end()); Func bounded("mirror_interior"); bounded(args) = source(actuals); return bounded; }
/** * Adjust the size of a sibling. */ void MythUIType::AdjustMinArea(int delta_x, int delta_y, int delta_w, int delta_h) { // If a minsize is not set, don't use MinArea if (!m_MinSize.isValid()) return; // Delta's are negative values; knock down the area QRect bounded(m_Area.x() - delta_x, m_Area.y() - delta_y, m_Area.width() + delta_w, m_Area.height() + delta_h); // Make sure we have not violated the min size if (!bounded.isNull() || !m_Vanish) { QPoint center = bounded.center(); if (bounded.isNull()) bounded.setSize(GetMinSize()); else bounded.setSize(bounded.size().expandedTo(GetMinSize())); bounded.moveCenter(center); } if (bounded.x() + bounded.width() > m_Area.x() + m_Area.width()) bounded.moveRight(m_Area.x() + m_Area.width()); if (bounded.y() + bounded.height() > m_Area.y() + m_Area.height()) bounded.moveBottom(m_Area.x() + m_Area.height()); if (bounded.x() < m_Area.x()) { bounded.moveLeft(m_Area.x()); if (bounded.width() > m_Area.width()) bounded.setWidth(m_Area.width()); } if (bounded.y() < m_Area.y()) { bounded.moveTop(m_Area.y()); if (bounded.height() > m_Area.height()) bounded.setHeight(m_Area.height()); } m_MinArea = bounded; m_Vanished = false; QList<MythUIType *>::iterator it; for (it = m_ChildrenList.begin(); it != m_ChildrenList.end(); ++it) { if (!(*it)->m_Initiator) (*it)->AdjustMinArea(delta_x, delta_y, delta_w, delta_h); } }
/** * Set the minimum area based on the given size */ void MythUIType::SetMinArea(const QSize &size) { // If a minsize is not set, don't use MinArea if (!m_Initiator || !m_MinSize.isValid()) return; m_MinArea.setWidth(0); if (m_Area.width() < m_NormalSize.width()) m_Area.setWidth(m_NormalSize.width()); if (m_Area.height() < m_NormalSize.height()) m_Area.setHeight(m_NormalSize.height()); /** * The MinArea will have the same origin as the normal Area, * but can have a smaller size. */ QSize bounded(size); if (!bounded.isNull() || !m_Vanish) { if (bounded.isNull()) bounded = GetMinSize(); else bounded = bounded.expandedTo(GetMinSize()); bounded = bounded.boundedTo(m_Area.size()); } if (m_Vanish == m_Vanished && bounded == m_MinArea.size()) return; m_MinArea.setWidth(bounded.width()); m_MinArea.setHeight(bounded.height()); m_Vanished = (m_Vanish && m_MinArea.size().isNull()); if (m_Vanished) { m_MinArea.moveLeft(0); m_MinArea.moveTop(0); } else { m_MinArea.moveLeft(m_Area.x()); m_MinArea.moveTop(m_Area.y()); } if (m_Parent) m_Parent->SetMinAreaParent(m_MinArea, m_Area, this); }
Func constant_exterior(const Func &source, Tuple value, const std::vector<std::pair<Expr, Expr>> &bounds) { std::vector<Var> args(source.args()); user_assert(args.size() >= bounds.size()) << "constant_exterior called with more bounds (" << bounds.size() << ") than dimensions (" << source.args().size() << ") Func " << source.name() << "has.\n"; Expr out_of_bounds = cast<bool>(false); for (size_t i = 0; i < bounds.size(); i++) { Var arg_var = source.args()[i]; Expr min = bounds[i].first; Expr extent = bounds[i].second; if (min.defined() && extent.defined()) { out_of_bounds = (out_of_bounds || arg_var < min || arg_var >= min + extent); } else if (min.defined() || extent.defined()) { user_error << "Partially undefined bounds for dimension " << arg_var << " of Func " << source.name() << "\n"; } } Func bounded("constant_exterior"); if (value.as_vector().size() > 1) { std::vector<Expr> def; for (size_t i = 0; i < value.as_vector().size(); i++) { def.push_back(select(out_of_bounds, value[i], repeat_edge(source, bounds)(args)[i])); } bounded(args) = Tuple(def); } else { bounded(args) = select(out_of_bounds, value[0], repeat_edge(source, bounds)(args)); } return bounded; }
/* * runGame * * sequence through each player taking turns, until there is a winner or * players get "bored" (reach max turns) * */ void GameRunner::runGame() { int currentPlayerNum = selectStartingPlayer(); // starting player int turnCount = 0; while (!game.hasWinner() && (++turnCount < maxTurns)) { turn(currentPlayerNum); // sequence through next player's turn showProgress(); int numPlayers = game.getPlayers().size(); // current num players in game currentPlayerNum = bounded(++currentPlayerNum, numPlayers); // advance to next player } }
/** * Set the minimum area based on the given size */ void MythUIType::SetMinArea(const MythRect &rect) { // If a minsize is not set, don't use MinArea if (!m_Initiator || !m_MinSize.isValid()) return; QRect bounded(rect); bool vanish = (m_Vanish && rect.isNull()); if (vanish) { bounded.moveLeft(0); bounded.moveTop(0); } else { QPoint center = bounded.center(); if (bounded.isNull()) bounded.setSize(GetMinSize()); else bounded.setSize(bounded.size().expandedTo(GetMinSize())); bounded.moveCenter(center); if (bounded.x() + bounded.width() > m_Area.x() + m_Area.width()) bounded.moveRight(m_Area.x() + m_Area.width()); if (bounded.y() + bounded.height() > m_Area.y() + m_Area.height()) bounded.moveBottom(m_Area.x() + m_Area.height()); if (bounded.x() < m_Area.x()) { bounded.moveLeft(m_Area.x()); if (bounded.width() > m_Area.width()) bounded.setWidth(m_Area.width()); } if (bounded.y() < m_Area.y()) { bounded.moveTop(m_Area.y()); if (bounded.height() > m_Area.height()) bounded.setHeight(m_Area.height()); } } m_MinArea = bounded; m_Vanished = vanish; if (m_Parent) m_Parent->SetMinAreaParent(m_MinArea, m_Area, this); }
static int shift_all(shifter_dd *dt, void **wdata, int what, void **where, multi_ext *mx) { int i, j, rows = mx->nrows; /* Sanity check */ if ((rows > NSHIFT) || (mx->ncols > 3) || (mx->mincols < 3) || (mx->fractcol >= 0)) return (0); // Error for (i = 0; i < rows; i++) { int *row = mx->rows[i] + 1; for (j = 0; j < 3; j++) spins[i][j][0] = bounded(row[j], 0, spins[i][j][2]); } for (; i < NSHIFT; i++) spins[i][0][0] = spins[i][1][0] = spins[i][2][0] = 0; reset_frames(dt); return (1); }
void vmWishboneCar::simControl() { // auto align steering angle if (manualYes) steerGain= 10; else { steerGain= 10; steer*= 0.98; speed*= 0.999; } dReal dsteer, realSpeed; //dsteer = bounded(steer,-40.0,40.0) - dJointGetHingeAngle(frWheel.joint); realSpeed = -bounded(speed, -14*M_PI, 30*M_PI); // steer /*dJointSetHingeParam(frWheel.joint, dParamVel, steerGain*dsteer+0.01*dsteer/0.01); dJointSetHingeParam(frWheel.joint, dParamFMax, 1000.0); dJointSetHingeParam (frWheel.joint,dParamLoStop,-40.0*M_PI/180.0); dJointSetHingeParam (frWheel.joint,dParamHiStop,40.0*M_PI/180.0); dJointSetHingeParam (frWheel.joint,dParamFudgeFactor,0.1); dJointSetHinge2Param(flWheel.joint, dParamVel, steerGain*dsteer+0.01*dsteer/0.01); dJointSetHinge2Param(flWheel.joint, dParamFMax, 1000.0); dJointSetHinge2Param (flWheel.joint,dParamLoStop,-40.0*M_PI/180.0); dJointSetHinge2Param (flWheel.joint,dParamHiStop,40.0*M_PI/180.0); dJointSetHinge2Param (flWheel.joint,dParamFudgeFactor,0.1);*/ // speed if (brakeYes) { dReal factor= 0.1; dJointSetHingeParam(rrSuspension.jRotorMid, dParamVel ,dJointGetHingeParam(rrSuspension.jRotorMid,dParamVel)*factor); dJointSetHingeParam(rrSuspension.jRotorMid, dParamFMax, 1000.0); dJointSetHingeParam(rlSuspension.jRotorMid, dParamVel ,dJointGetHingeParam(rlSuspension.jRotorMid,dParamVel)*factor); dJointSetHingeParam(rlSuspension.jRotorMid, dParamFMax, 1000.0); dJointSetHingeParam(frSuspension.jRotorMid, dParamVel, realSpeed);//dJointGetHinge2Param(frWheel.joint,dParamVel2)*factor); dJointSetHingeParam(frSuspension.jRotorMid, dParamFMax, 1000.0); dJointSetHingeParam(flSuspension.jRotorMid, dParamVel, realSpeed);//dJointGetHinge2Param(flWheel.joint,dParamVel2)*factor); dJointSetHingeParam(flSuspension.jRotorMid, dParamFMax, 1000.0); } else { // turn off rear wheels dJointSetHingeParam(rrSuspension.jRotorMid, dParamFMax, 0.0); dJointSetHingeParam(rlSuspension.jRotorMid, dParamFMax, 0.0); // set up front wheels dJointSetHingeParam(frSuspension.jRotorMid, dParamVel, realSpeed); dJointSetHingeParam(frSuspension.jRotorMid, dParamFMax, 500.0); dJointSetHingeParam(flSuspension.jRotorMid, dParamVel, realSpeed); dJointSetHingeParam(flSuspension.jRotorMid, dParamFMax, 500.0); //printf("real speed: %f", realSpeed); } // reset manual mode flag manualYes= 0; }
/**Set a filter on the output to reduce sharp oscillations. <br> * 0.1 is likely a sane starting value. Larger values P and D oscillations, but force larger I values. * Uses an exponential rolling sum filter, according to a simple <br> * <pre>output*(1-strength)*sum(0..n){output*strength^n}</pre> * @param output valid between [0..1), meaning [current output only.. historical output only) */ void MiniPID::setOutputFilter(double strength){ if(strength==0 || bounded(strength,0,1)){ outputFilter=strength; } }
/** Calculate the PID value needed to hit the target setpoint. * Automatically re-calculates the output at each call. * @param actual The monitored value * @param target The target value * @return calculated output value for driving the actual to the target */ double MiniPID::getOutput(double actual, double setpoint){ double output; double Poutput; double Ioutput; double Doutput; double Foutput; this->setpoint=setpoint; //Ramp the setpoint used for calculations if user has opted to do so if(setpointRange!=0){ setpoint=clamp(setpoint,actual-setpointRange,actual+setpointRange); } //Do the simple parts of the calculations double error=setpoint-actual; //Calculate F output. Notice, this->depends only on the setpoint, and not the error. Foutput=F*setpoint; //Calculate P term Poutput=P*error; //If this->is our first time running this-> we don't actually _have_ a previous input or output. //For sensor, sanely assume it was exactly where it is now. //For last output, we can assume it's the current time-independent outputs. if(firstRun){ lastActual=actual; lastOutput=Poutput+Foutput; firstRun=false; } //Calculate D Term //Note, this->is negative. this->actually "slows" the system if it's doing //the correct thing, and small values helps prevent output spikes and overshoot Doutput= -D*(actual-lastActual); lastActual=actual; //The Iterm is more complex. There's several things to factor in to make it easier to deal with. // 1. maxIoutput restricts the amount of output contributed by the Iterm. // 2. prevent windup by not increasing errorSum if we're already running against our max Ioutput // 3. prevent windup by not increasing errorSum if output is output=maxOutput Ioutput=I*errorSum; if(maxIOutput!=0){ Ioutput=clamp(Ioutput,-maxIOutput,maxIOutput); } //And, finally, we can just add the terms up output=Foutput + Poutput + Ioutput + Doutput; //Figure out what we're doing with the error. if(minOutput!=maxOutput && !bounded(output, minOutput,maxOutput) ){ errorSum=error; // reset the error sum to a sane level // Setting to current error ensures a smooth transition when the P term // decreases enough for the I term to start acting upon the controller // From that point the I term will build up as would be expected } else if(outputRampRate!=0 && !bounded(output, lastOutput-outputRampRate,lastOutput+outputRampRate) ){ errorSum=error; } else if(maxIOutput!=0){ errorSum=clamp(errorSum+error,-maxError,maxError); // In addition to output limiting directly, we also want to prevent I term // buildup, so restrict the error directly } else{ errorSum+=error; } //Restrict output to our specified output and ramp limits if(outputRampRate!=0){ output=clamp(output, lastOutput-outputRampRate,lastOutput+outputRampRate); } if(minOutput!=maxOutput){ output=clamp(output, minOutput,maxOutput); } if(outputFilter!=0){ output=lastOutput*outputFilter+output*(1-outputFilter); } lastOutput=output; return output; }
*/ #include <sys/param.h> #include <stdio.h> #include <stdlib.h> #include <zlib.h> #include "defs.h" #include "compress.h" __RCSID("$MirOS: contrib/hosted/fwcf/c_zlib.c,v 1.4 2006/09/23 23:46:35 tg Exp $"); static void c_zlib_load(void) __attribute__((constructor)); static int c_init(void); static int c_compress(char **, char *, size_t) __attribute__((bounded (string, 2, 3))); static int c_decompress(char *, size_t, char *, size_t) __attribute__((bounded (string, 1, 2))) __attribute__((bounded (string, 3, 4))); static fwcf_compressor c_zlib = { c_init, /* init */ c_compress, /* compress */ c_decompress, /* decompress */ "zlib", /* name */ 0x01 /* code */ }; static void c_zlib_load(void) {
/** * Return a random point in a generic shape. * @param object an IObject within which the point is generated * @param rng a random number generator * @param maxAttempts maximum number of random numbers to use before giving up * @return a point */ boost::optional<Kernel::V3D> inGenericShape(const IObject &object, Kernel::PseudoRandomNumberGenerator &rng, size_t maxAttempts) { return bounded(object, rng, object.getBoundingBox(), maxAttempts); }
/* * selectStartingPlayer * * who rolls first (random) * */ int GameRunner::selectStartingPlayer() { // best roll wins - but this is simply by chance => just use the chance from a single roll! return bounded(game.getDice().roll(), game.getPlayers().size()); }
int goSomewhere(struct state *s, char **a, int penalty){ int i,j, is, js, k, wx=0, wy=0, stage=-1; unsigned int change = 0, end = 0; struct state *ns; char * answer; char move='U'; unsigned int *c = malloc( ((s-> world_w+1) * s->world_h+1) * sizeof( unsigned int )); if (c == NULL ){} for(i=0; i<((s-> world_w+1) * s->world_h+1); i++){ c[i]=UINT_MAX; } c[point_to_index(s, s->robot_x, s->robot_y)]=0; put(s, 1, 1, O_EMPTY); move_robot(s, 1, 1); ns = copy(s); do{ free(s); s = copy(ns); update_world(ns, s); change++; stage++; end = 0; for(i=1; i <= s->world_w; i++){ for(j=1; j <= s->world_h; j++){ if(c[point_to_index(s,i,j)]==stage){ if(get(s, i, j) == O_LIFT_OPEN || get(s, i, j) == O_LAMBDA){ wx=i; wy=j; end=stage; break; } //consider four cells - (-1, 0), (1, 0), (0, -1), (0, 1) for(k = 1; k<=4; k++){ if(k==1) {is= 0 ; js=-1;} if(k==2) {is= 0 ; js= 1;} if(k==3) {is=-1 ; js= 0;} if(k==4) {is= 1 ; js= 0;} if(bounded(s,i+is,j+js) && c[point_to_index(s, i+is, j+js)]==UINT_MAX){ //can we go there? if( !bounded(s, i+is, j+js+1) || (get(s, i+is, j+js+1) != O_EMPTY || get(ns, i+is, j+js+1) != O_ROCK)){ if(get(s, i+is, j+js)==O_LIFT_OPEN || get(s, i+is, j+js)==O_LAMBDA || get(s, i+is, j+js)==O_EARTH || get(s, i+is, j+js)==O_EMPTY){ if((bounded(s, i+is, j+js+1) && get(s, i+is, j+js+1)==O_ROCK) || (bounded(s, i+is+1, j+js+1) && get(s, i+is+1, j+js)==O_ROCK && get(s, i+is+1, j+js+1)==O_ROCK) || (bounded(s, i+is-1, j+js+1) && get(s, i+is-1, j+js)==O_ROCK && get(s, i+is-1, j+js+1)==O_ROCK)){ c[point_to_index(s, i+is, j+js)]=stage+penalty; }else{ c[point_to_index(s, i+is, j+js)]=stage+1; } change = 0; } } } } } } } }while(change <= penalty && end == 0); //debug //dump(s); if(0){ for(j=s->world_h; j>0; j--){ for(i=1; i<=s->world_w; i++){ if(c[point_to_index(s, i, j)]==UINT_MAX){ printf("X"); }else{ printf("%u", c[point_to_index(s, i, j)]); } } printf("\n"); } printf("\n"); } i=0; if(end>0){ answer = malloc( (end+2)*sizeof( char )); if (answer == NULL ){} while(end>0){ for(k=1; k<=4;k++){ if(k==1) {is=-1; js= 0;move='R';} if(k==2) {is= 1; js= 0;move='L';} if(k==3) {is= 0; js=-1;move='U';} if(k==4) {is= 0; js= 1;move='D';} if( bounded(s, wx+is, wy+js) && c[point_to_index(s, wx+is, wy+js)] < end) { end = c[point_to_index(s, wx+is, wy+js)]; answer[i++]=move; wx = wx+is; wy = wy+js; break; } } } answer[i]='\0'; reverse(answer,0,strlen(answer)-1); }else{ answer = malloc(1*sizeof( char )); if (answer == NULL ){} answer[0]='\0'; *a=answer; free(c); return 1; } *a=answer; free(c); return 0; }