Project

Profile

Help

HostedRedmine.com has moved to the Planio platform. All logins and passwords remained the same. All users will be able to login and use Redmine just as before. Read more...

Bug #879104 » 0006-Don-t-punish-non-revealing-illegal-moves.patch

Sveinung Kvilhaugsvik, 2020-06-25 01:00 PM

View differences:

doc/README.effects
288 288

  
289 289
Illegal_Action_Move_Cost
290 290
    The number of move fragments lost when the player tries to do an action
291
that turns out to be illegal.
291
that turns out to be illegal. Only applied when the player wasn't aware that
292
the action was illegal and its illegality therefore reveals new information.
292 293

  
293 294
Action_Success_Actor_Move_Cost
294 295
    The number of move fragments lost when a unit successfully performs an
server/unithand.c
2407 2407
}
2408 2408

  
2409 2409
/**********************************************************************//**
2410
  Tell the client that the action it requested is illegal. This can be
2411
  caused by the player (and therefore the client) not knowing that some
2412
  condition of an action no longer is true.
2410
  Punish a player for trying to perform an action that turned out to be
2411
  illegal. The punishment, if any at all, is specified by the ruleset.
2412
  @param pplayer the player to punish.
2413
  @param information_revealed if finding out that the action is illegal
2414
                              reveals new information.
2415
  @param act_unit the actor unit performing the action.
2416
  @param stopped_action the illegal action.
2417
  @param tgt_player the intended target of the action.
2418
  @param requester who ordered the action performed?
2419
  @return TRUE iff player was punished for trying to do the illegal action.
2413 2420
**************************************************************************/
2414
static void illegal_action(struct player *pplayer,
2415
                           struct unit *actor,
2416
                           action_id stopped_action,
2417
                           struct player *tgt_player,
2418
                           const struct tile *target_tile,
2419
                           const struct city *target_city,
2420
                           const struct unit *target_unit,
2421
                           bool disturb_player,
2422
                           const enum action_requester requester)
2421
static bool illegal_action_pay_price(struct player *pplayer,
2422
                                     bool information_revealed,
2423
                                     struct unit *act_unit,
2424
                                     struct action *stopped_action,
2425
                                     struct player *tgt_player,
2426
                                     const enum action_requester requester)
2423 2427
{
2424 2428
  int punishment_mp;
2425 2429

  
2426
  /* Why didn't the game check before trying something illegal? Did a good
2427
   * reason to not call is_action_enabled_unit_on...() appear? The game is
2428
   * omniscient... */
2429
  fc_assert(requester != ACT_REQ_RULES);
2430

  
2431 2430
  /* Don't punish the player for something the game did. Don't tell the
2432 2431
   * player that the rules required the game to try to do something
2433 2432
   * illegal. */
2434
  fc_assert_ret_msg((requester == ACT_REQ_PLAYER
2435
                     || requester == ACT_REQ_SS_AGENT),
2436
                    "The player wasn't responsible for this.");
2433
  fc_assert_ret_val_msg((requester == ACT_REQ_PLAYER
2434
                         || requester == ACT_REQ_SS_AGENT),
2435
                        FALSE,
2436
                        "The player wasn't responsible for this.");
2437

  
2438
  if (!information_revealed) {
2439
    /* The player already had enough information to determine that this
2440
     * action is illegal. Don't punish a client error or an accident. */
2441
    return FALSE;
2442
  }
2437 2443

  
2438 2444
  /* The mistake may have a cost. */
2439 2445
  punishment_mp = get_target_bonus_effects(NULL,
2440
                                           unit_owner(actor),
2446
                                           unit_owner(act_unit),
2441 2447
                                           tgt_player,
2442 2448
                                           NULL,
2443 2449
                                           NULL,
2444 2450
                                           NULL,
2445
                                           actor,
2446
                                           unit_type_get(actor),
2451
                                           act_unit,
2452
                                           unit_type_get(act_unit),
2447 2453
                                           NULL,
2448 2454
                                           NULL,
2449
                                           action_by_number(stopped_action),
2455
                                           stopped_action,
2450 2456
                                           EFT_ILLEGAL_ACTION_MOVE_COST);
2451 2457

  
2452
  actor->moves_left = MAX(0, actor->moves_left - punishment_mp);
2458
  /* Stay in range */
2459
  punishment_mp = MAX(0, punishment_mp);
2453 2460

  
2454
  send_unit_info(NULL, actor);
2461
  /* Punish the unit's move fragments. */
2462
  act_unit->moves_left = MAX(0, act_unit->moves_left - punishment_mp);
2463
  send_unit_info(NULL, act_unit);
2455 2464

  
2456
  if (punishment_mp) {
2465
  if (punishment_mp != 0) {
2457 2466
    /* The player probably wants to be disturbed if his unit was punished
2458 2467
     * with the loss of movement points. */
2459
    notify_player(pplayer, unit_tile(actor),
2468
    notify_player(pplayer, unit_tile(act_unit),
2460 2469
                  E_UNIT_ILLEGAL_ACTION, ftc_server,
2461 2470
                  /* TRANS: Spy ... movement point text that may include
2462 2471
                   * fractions. */
2463 2472
                  _("Your %s lost %s MP for attempting an illegal action."),
2464
                  unit_name_translation(actor),
2473
                  unit_name_translation(act_unit),
2465 2474
                  move_points_text(punishment_mp, TRUE));
2466 2475
  }
2467 2476

  
2468
  if (disturb_player || punishment_mp) {
2477
  return punishment_mp != 0;
2478
}
2479

  
2480
/**********************************************************************//**
2481
  Tell the client that the action it requested is illegal. This can be
2482
  caused by the player (and therefore the client) not knowing that some
2483
  condition of an action no longer is true.
2484
**************************************************************************/
2485
static void illegal_action(struct player *pplayer,
2486
                           struct unit *actor,
2487
                           action_id stopped_action_id,
2488
                           struct player *tgt_player,
2489
                           const struct tile *target_tile,
2490
                           const struct city *target_city,
2491
                           const struct unit *target_unit,
2492
                           bool disturb_player,
2493
                           const enum action_requester requester)
2494
{
2495
  bool information_revealed;
2496
  bool was_punished;
2497

  
2498
  struct action *stopped_action = action_by_number(stopped_action_id);
2499

  
2500
  /* Why didn't the game check before trying something illegal? Did a good
2501
   * reason to not call is_action_enabled_unit_on...() appear? The game is
2502
   * omniscient... */
2503
  fc_assert(requester != ACT_REQ_RULES);
2504

  
2505

  
2506
  information_revealed = action_prob_possible(action_prob_unit_vs_tgt(
2507
                                                 stopped_action,
2508
                                                 actor,
2509
                                                 target_city, target_unit,
2510
                                                 target_tile, NULL));
2511

  
2512
  was_punished = illegal_action_pay_price(pplayer, information_revealed,
2513
                                          actor, stopped_action, tgt_player,
2514
                                          requester);
2515

  
2516
  if (disturb_player || was_punished) {
2469 2517
    /* This is a foreground request or the actor unit was punished with
2470 2518
     * the loss of movement points. */
2471
    illegal_action_msg(pplayer, E_UNIT_ILLEGAL_ACTION,
2472
                       actor, stopped_action,
2519
    illegal_action_msg(pplayer, (information_revealed
2520
                                 ? E_UNIT_ILLEGAL_ACTION : E_BAD_COMMAND),
2521
                       actor, stopped_action_id,
2473 2522
                       target_tile, target_city, target_unit);
2474 2523
  }
2475 2524
}
2476
- 
(1-1/2)