~widelands-dev/widelands/trunk

« back to all changes in this revision

Viewing changes to src/logic/map_objects/tribes/production_program.cc

  • Committer: The Widelands Bunnybot
  • Date: 2020-08-15 06:09:43 UTC
  • Revision ID: bunnybot@widelands.org-20200815060943-j3nda0lqh09nj8kl
Use named parameters in ActMine (#4099)

The worker experience parameter is now optional.

(by gunchleoc)
2fc976bf387e701d88a32754904994ca636600a1

Show diffs side-by-side

added added

removed removed

Lines of Context:
1272
1272
/* RST
1273
1273
mine
1274
1274
----
1275
 
Takes resources from the ground. It takes as arguments first the resource
1276
 
name, after this the radius for searching for the resource around the building
1277
 
field. The next values is the percentage of starting resources that can be dug
1278
 
out before this mine is exhausted. The next value is the percentage that this
1279
 
building still produces something even if it is exhausted. And the last value
1280
 
is the percentage chance that a worker is gaining experience on failure - this
1281
 
is to guarantee that you can eventually extend a mine, even though it was
1282
 
exhausted for a while already.
 
1275
 
 
1276
.. function:: mine=\<resource_name\> radius:\<number\> resources:\<percent\> when_empty:\<percent\>
 
1277
     \[experience_on_fail:\<percent\>\]
 
1278
 
 
1279
   :arg string resource_name: The name of the resource to mine, e.g. 'coal' or 'water'.
 
1280
   :arg int radius: The workarea radius that is searched for resources. Must be ``>0``.
 
1281
   :arg percent yield: The :ref:`map_object_programs_datatypes_percent` of resources that the
 
1282
      mine can dig up before its resource is depleted.
 
1283
   :arg percent when_empty: The :ref:`map_object_programs_datatypes_percent` chance that the mine
 
1284
      will still find some resources after it has been depleted.
 
1285
   :arg percent experience_on_fail: The :ref:`map_object_programs_datatypes_percent` chance that the
 
1286
      mine's workers will still gain some experience when mining fails after its resources have been
 
1287
      depleted.
 
1288
 
 
1289
   Takes resources from the ground. A building that mines will deplete when the percentage of
 
1290
   resources given in ``resources`` has been dug up, leaving a chance of ``depleted`` that it
 
1291
   will still find some resources anyway. Examples:
 
1292
 
 
1293
.. code-block:: lua
 
1294
 
 
1295
     actions = {
 
1296
         "return=skipped unless economy needs iron_ore",
 
1297
         "consume=ration",
 
1298
         "sleep=duration:45s",
 
1299
         "animate=working duration:20s",
 
1300
          -- Search radius of 2 for iron. Will always find iron until 33.33% of it has been dug up.
 
1301
          -- After that, there's still a chance of 5% for finding iron.
 
1302
          -- If this fails, the workers still have a chance of 17% of gaining experience.
 
1303
         "mine=iron radius:2 yield:33.33% when_empty:5% experience_on_fail:17%",
 
1304
         "produce=iron_ore"
 
1305
     }
 
1306
 
 
1307
     actions = {
 
1308
         "sleep=duration:20s",
 
1309
         "animate=working duration:20s",
 
1310
          -- Search radius of 1 for water. Will always find water until 100% of it has been drawn.
 
1311
          -- After that, there's still a chance of 65% for finding water.
 
1312
         "mine=water radius:1 yield:100% when_empty:65%",
 
1313
         "produce=water"
 
1314
     }
1283
1315
*/
1284
1316
ProductionProgram::ActMine::ActMine(const std::vector<std::string>& arguments,
1285
1317
                                    const World& world,
1286
1318
                                    const std::string& production_program_name,
1287
1319
                                    ProductionSiteDescr* descr) {
1288
 
        if (arguments.size() != 5) {
1289
 
                throw GameDataError(
1290
 
                   "Usage: mine=resource <workarea radius> <max> <chance> <worker experience gained>");
 
1320
        if (arguments.size() != 5 && arguments.size() != 4) {
 
1321
                throw GameDataError("Usage: mine=<resource name> radius:<number> yield:<percent> "
 
1322
                                    "when_empty:<percent> [experience:<percent>]");
1291
1323
        }
 
1324
        experience_chance_ = 0U;
1292
1325
 
1293
 
        resource_ = world.safe_resource_index(arguments.front().c_str());
1294
 
        distance_ = read_positive(arguments.at(1));
1295
 
        max_ = read_positive(arguments.at(2));
1296
 
        chance_ = read_positive(arguments.at(3));
1297
 
        training_ = read_positive(arguments.at(4));
 
1326
        if (read_key_value_pair(arguments.at(2), ':').second.empty()) {
 
1327
                // TODO(GunChleoc): Savegame compatibility, remove after v1.0
 
1328
                log("WARNING: Using old syntax in %s. Please use 'mine=<resource name> radius:<number> "
 
1329
                    "yield:<percent> when_empty:<percent> [experience_on_fail:<percent>]'\n",
 
1330
                    descr->name().c_str());
 
1331
                resource_ = world.safe_resource_index(arguments.front().c_str());
 
1332
                workarea_ = read_positive(arguments.at(1));
 
1333
                max_resources_ = read_positive(arguments.at(2)) * 100U;
 
1334
                depleted_chance_ = read_positive(arguments.at(3)) * 100U;
 
1335
                if (arguments.size() == 5) {
 
1336
                        experience_chance_ = read_positive(arguments.at(4)) * 100U;
 
1337
                }
 
1338
        } else {
 
1339
                for (const std::string& argument : arguments) {
 
1340
                        const std::pair<std::string, std::string> item = read_key_value_pair(argument, ':');
 
1341
                        if (item.second.empty()) {
 
1342
                                resource_ = world.safe_resource_index(item.first.c_str());
 
1343
                        } else if (item.first == "radius") {
 
1344
                                workarea_ = read_positive(item.second);
 
1345
                        } else if (item.first == "yield") {
 
1346
                                max_resources_ = read_percent_to_int(item.second);
 
1347
                        } else if (item.first == "when_empty") {
 
1348
                                depleted_chance_ = read_percent_to_int(item.second);
 
1349
                        } else if (item.first == "experience_on_fail") {
 
1350
                                experience_chance_ = read_percent_to_int(item.second);
 
1351
                        } else {
 
1352
                                throw GameDataError(
 
1353
                                   "Unknown argument '%s'. Usage: mine=<resource name> radius:<number> "
 
1354
                                   "yield:<percent> when_empty:<percent> [experience_on_fail:<percent>]",
 
1355
                                   item.first.c_str());
 
1356
                        }
 
1357
                }
 
1358
        }
1298
1359
 
1299
1360
        const std::string description = descr->name() + " " + production_program_name + " mine " +
1300
1361
                                        world.get_resource(resource_)->name();
1301
 
        descr->workarea_info_[distance_].insert(description);
 
1362
        descr->workarea_info_[workarea_].insert(description);
1302
1363
 
1303
1364
        descr->add_collected_resource(arguments.front());
1304
1365
}
1313
1374
 
1314
1375
        {
1315
1376
                MapRegion<Area<FCoords>> mr(
1316
 
                   *map, Area<FCoords>(map->get_fcoords(ps.get_position()), distance_));
 
1377
                   *map, Area<FCoords>(map->get_fcoords(ps.get_position()), workarea_));
1317
1378
                do {
1318
1379
                        DescriptionIndex fres = mr.location().field->get_resources();
1319
1380
                        ResourceAmount amount = mr.location().field->get_resources_amount();
1343
1404
                } while (mr.advance(*map));
1344
1405
        }
1345
1406
 
1346
 
        //  how much is digged
1347
 
        int32_t digged_percentage = 100;
 
1407
        //  how much is dug
 
1408
        unsigned dug_percentage = MapObjectProgram::kMaxProbability;
1348
1409
        if (totalstart) {
1349
 
                digged_percentage = (totalstart - totalres) * 100 / totalstart;
 
1410
                dug_percentage = (totalstart - totalres) * MapObjectProgram::kMaxProbability / totalstart;
1350
1411
        }
1351
1412
        if (!totalres) {
1352
 
                digged_percentage = 100;
 
1413
                dug_percentage = MapObjectProgram::kMaxProbability;
1353
1414
        }
1354
1415
 
1355
 
        if (digged_percentage < max_) {
 
1416
        if (dug_percentage < max_resources_) {
1356
1417
                //  mine can produce normally
1357
1418
                if (totalres == 0) {
1358
1419
                        return ps.program_end(game, ProgramResult::kFailed);
1364
1425
 
1365
1426
                {
1366
1427
                        MapRegion<Area<FCoords>> mr(
1367
 
                           *map, Area<FCoords>(map->get_fcoords(ps.get_position()), distance_));
 
1428
                           *map, Area<FCoords>(map->get_fcoords(ps.get_position()), workarea_));
1368
1429
                        do {
1369
1430
                                DescriptionIndex fres = mr.location().field->get_resources();
1370
1431
                                ResourceAmount amount = mr.location().field->get_resources_amount();
1393
1454
                //  there is a sufficiently high chance, that the mine
1394
1455
                //  will still produce enough.
1395
1456
                //  e.g. mines have chance=5, wells have 65
1396
 
                if (chance_ <= 20) {
 
1457
                if (depleted_chance_ <= 20 * MapObjectProgram::kMaxProbability / 100U) {
1397
1458
                        ps.notify_player(game, 60);
1398
1459
                        // and change the default animation
1399
1460
                        ps.set_default_anim("empty");
1402
1463
                //  Mine has reached its limits, still try to produce something but
1403
1464
                //  independent of sourrunding resources. Do not decrease resources
1404
1465
                //  further.
1405
 
                if (chance_ <= game.logic_rand() % 100) {
 
1466
                if (depleted_chance_ <= game.logic_rand() % MapObjectProgram::kMaxProbability) {
1406
1467
 
1407
1468
                        // Gain experience
1408
 
                        if (training_ >= game.logic_rand() % 100) {
 
1469
                        if (experience_chance_ > 0 &&
 
1470
                            experience_chance_ >= game.logic_rand() % MapObjectProgram::kMaxProbability) {
1409
1471
                                ps.train_workers(game);
1410
1472
                        }
1411
1473
                        return ps.program_end(game, ProgramResult::kFailed);