design patterns – Robins magic Chess game: Where to put/split the behaviour to full fill Law of Demeter

So now i have a really concrete example;
its highly related to that question here: Tell one, but ask the others?

the important statements there are:


In the comment section https://softwareengineering.stackexchange.com/a/418453/347781 :

But what you would say if both sides pull out the data?, ok i put the behaviour to the Chatroom, but the Chatroom pulls then out the data from the user, because it needs to fullfill its algorithm data from both,……. maybe then we have a third party, fourth and so on, The Chatroom would pull out data from all of the others. What kind of benefit i have to put then the behaviour to the Chatroom. On which metric i can decide to put it to the Chatroom, because you said placing the bevahiour to that location, which dont pull out data, but if each one of them pull out data?^^ – Robin Kreuzer

@RobinKreuzer You have to come up with a design in which no objects pull data out of other objects (some rare exceptions apply). That is what object-orientation is at its core. Objects are there to contribute behavior. It is the key factor that makes oo more maintainable than procedural programming. – Robert Bräutigam

and my abstract example here:

if(
something from user &&
something from ChatRoom &&
something from something deep in the user, maybe the color of the users fingernail? &&
something merged from user and Chatroom (the niceLevels for example) &&
something from clock &&
something ....
)

then

{
change some state in the user
change some state in the ChatRoom
change some state in the niceLevels of user and ChatRoom
change maybe the clock?
change something in a third-party-object, which was not in the if-checks (maybe sending a notification/email or something else)
change some state in ....
}

the quote and the abstract code example are both from the Tell one, but ask the others topic
the abstract example should show how complex interacting/collaborations of objects could be; that it is not that easy like Robert Bräutigam claim in his quote.


Now i want to give a concrete example/question:

Let’s take a chess game, if a client/user wants to move the tower five spaces forward, then there must be a few constraints full-filled.

  • The tower is not allowed to cross an own figure or a other figure (a
    horse is allowed to do so)
  • The tower can throw hostile a figure from the game if it is on field five spaces
    forward from him.
  • And so on

Now i want to add some game-rules:

  • If the a hostile figure is threw away, all fields the tower touched
    are colored red, if no figure is threw from the game, all fields the
    tower touched are colored grey. The horse color its field in all
    cases green.
  • If a tower and only the figure tower reaches the other side, the
    game-mode is changed, so all figure should now act in a other way.
    Maybe game-change could be that no more figures are allowed to be thrown
    from game the next 10 turns, and all figures are now only allowed to
    move in maximum 2 spaces
  • if a farmer reaches the other side, it is morphed to a queen and all
    towers a player left should morphe to horses
  • All figures can be named by the user and its movement action are counted, if a figure is morphed it keep that informations
  • a runner is only allowed to throw a hostile figure from the game, if itself moved at least 15 times and only 17 figures (sum of all figures from both teams) are left

And now we have there still a few more (more technically) requirements:

  • The client is only then allowed to move one of its figures, if when
    it is his turn^^
  • the game is controlled cli-based/text-based, so the user sends
    text-command to select one figure and signalize its movement (how you
    would dispatch this?)

So i think i have now a great NOT abstract examples, what was wished by so many of you.
Im interested now, how you would model this to full fill Robert Bräutigams constraints, which is more or less the same as Demeter had too.

A few thoughts from me

  • Maybe we can add the whole behaviour into the figures?, but then it
    have to pull out the state of the world around it?! -> a more or less procedural approach, because one code-actor/procedur acting on the other state?
  • Maybe we should try to divide the behavior into the figures and the
    world around, but i can’t see that the get there the wanted
    transactional-style. Also we get into trouble if we want to change
    the game-mode, we have to change it in all objects? And i think its
    not possible alone doing it that way, because we need merged-state
    (“runner is only allowed to throw (…) are left”) -> the hoped OO-approach from Robert Bräutigam?

.

Ok now i stop here with my thoughts^^, i don’t want to suggest that there is no solution on that i am interested in, that hopefully exists