Writing an MVC project for the first time - how close am I?
This is a little abstract, without much actual code, but perhaps it's useful nonetheless.

A game is actually a little tough to apply "stringent" MVC to. It's not quite clear cut what belongs where. The world is obviously a model, resources are obviously models, and tiles are too. But is a player a controller or a model? That's more difficult.

I'd say that you shouldn't worry about what the player is. Instead you should add an overall "game controller". Its responsibility would be to update resources before and after #turn is called on a player. The game controller would also be responsible for printing the world, etc., while the player would only responsible for actually making a turn (or, given that there seems to be 2 distinct parts to a turn, make those 2 separate methods). Return a decision (or two), and let the game controller and world sort out how to change the game state (reduce resources, update tiles, etc.).

You might also wait until this point to check the validity of a decision. Let the player make a decision first, and if it's nonsense, let the player try again. The player doesn't necessarily have to know the rules of the game, as long as the game controller knows 'em.

Never mind if the player is M, V, or C. Approach it simply as a "decision maker". It may be AI or a human player, but the point is that it returns a decision. It's sort of a controller, but I'd avoid having it update models or updating the view. It's basically a service object. It could even be completely stateless: Give it a world and a set of resources, and let it come up with a decision somehow.



In terms of code review:

My gut reaction is that there's too much going on in #turn. This is irrespective of the MVC design; the method is just doing too much. (In Ruby you often aim for methods that are super, super short. If you go above 5 lines, you need a reason. Above 10 lines, and you need a very good reason).

Many, if not all, of the UIHandler methods might work better as a module. They appear state-less, so it might well be simpler to just include them where necessary.

There are also some mixed responsibilities. You have tile.check_cost(decision, @resources) but you also have price = GameData.get_price(decision). If you can get the price yourself, you might as well check the cost yourself too. The check_cost method is nicely abstract - you don't need to worry about the cost, just if you can afford it. But that's undermined by you having to fetch the price later anyway.

On a micro level: To get a decision from the command line, I'd recommend something like

def get_decision(&amp;block)
  begin
    input = gets.chomp # or however you read input
  end until !block_given? || yield(input)
  input
end


which you then call like

decision = get_decision { |input| input.empty? || possible?(input) }


where possible? would be a method that checks tile.accepts?(input) and whether it fits the available resources.

Most of all, since there seems to be two steps in a "turn", I'd split those into separate methods. Again, have a game controller and let it call one method first, then the other.