Class: Monotony::DefaultBehaviour

Inherits:
Object
  • Object
show all
Defined in:
lib/monotony/behaviour.rb

Overview

Conains predefined behaviours

Constant Summary collapse

DEFAULT =
{
	purchase_possible: Proc.new { |game, player, property| 
		if player.properties.collect{ |p| p.set }.include? property.set
			# Will definitely buy if player already owns one or more of this set
			property.sell_to(player)
		elsif game.players.collect { |p| p.properties.collect { |p| p.set } }.flatten.include? property.set
			# Less likely to buy if another player already owns one of the set
			property.sell_to(player) if Random.rand(0..100) >= 75
		else
			# Will probably buy if nobody has bought any of this set yet
			property.sell_to(player) if Random.rand(0..100) >= 25
		end
	},
	unmortgage_possible: Proc.new { |game, player, property|
		# Only bother unmortgaging something if I have the rest of the set, or it's less than 15% of my cash
		if player.sets_owned.include? property.set
			property.unmortgage
		elsif ( property.cost.to_f / player.currency.to_f * 100.0 ) < 15.0
			property.unmortgage
		end
	},
	houses_available: Proc.new {|game, player, property|
		# Buy houses when possible, but don't spend more than 40% of my money on them in any one turn
		can_afford = ( ( player.currency * 0.4 ) / property.house_cost ).floor
		max_available = 4 - property.num_houses
		to_buy = [ can_afford, max_available ].min
		property.add_houses(to_buy) if to_buy > 0 unless game.active_players == 1
	},
	hotel_available: Proc.new {|game, player, property|
		# Buy a hotel, unless it's more than half my current balance.
		property.add_hotel unless ( property.hotel_cost.to_f / player.currency.to_f * 100.0) > 50.0
	},
	money_trouble: Proc.new {|game, player, amount|
		portfolio = player.properties.sort_by { |p| p.mortgage_value }
		while player.currency < amount do
			if portfolio.length > 0
				property = portfolio.shift
				if property.is_a? BasicProperty
					if property.num_hotels == 1
						property = property.sell_hotel
					end
					break if player.currency >= amount

					while property.num_houses > 0
						property = property.sell_houses(1)
						break if player.currency >= amount
					end
					break if player.currency >= amount

					property = property.mortgage
				end
			else
				break
			end
		end
	},
	use_jail_card: Proc.new {|game, player|
		# Unless less than 50% of active sets are mine, get out of jail with a card when possible
		player.use_jail_card! unless ( player.sets_owned.count.to_f / game.all_sets_owned.count.to_f * 100.0 ) < 50
	},
	trade_possible: Proc.new {|game, player|
		puts '[%s] Considering possible trades' % player.name
	    invested_colours = player.properties.collect(&:set).uniq
	    player.opponents.each do |opponent|
	    	opponent.properties.select { |r| invested_colours.include? r.set }.each do |desirable_property|
	    		factors = {}
	    		# e.g. 66% chance of buying if one property is owned, 99% chance of buying if two are
	    		factors[:number_owned] = ( desirable_property.number_of_set_owned.to_f + 1.0 ) / desirable_property.number_in_set(game).to_f
	    		# More likely to trade if player has over £1000
				factors[:currency] = player.currency.to_f / 1000.to_f
	    		# More likely to trade if close to GO
	    		factors[:proximity_to_go] = 1 - ( player.distance_to_go.to_f / game.board.length.to_f )

	    		# We use these factors to work out how much to offer relative to how much we have
	    		offer_amount = player.currency * factors.values.inject(&:*)
	    		if offer_amount > desirable_property.cost and player.currency >= offer_amount
					puts '[%s] Placing offer of £%d on %s (owned by %s) [%f]' % [ player.name, offer_amount, desirable_property.name, desirable_property.owner.name, factors.values.inject(&:*) * 100 ]

		    		desirable_property.place_offer(player, offer_amount)
		    	end
	    	end
	    end
	},
	trade_proposed: Proc.new {|game, player, proposer, property, amount|
		factors = {}
		# More likely to accept a trade the longer the game has been going on for (definitely at 100 turns)
		factors[:longevity] = ( [0, game.turn, 100].sort[1].to_f / 100.0 ).to_f
		# More likely to accept a trade if it is far over the list price
		factors[:value_added] = 1 - ( property.cost.to_f / amount.to_f )
		# More likely to accept a trade if low on cash
		factors[:currency] = 1 - ( player.currency.to_f / 1000.to_f )

		# Random element
		factors[:random] = Random.rand(1..100)
		puts '[%s] Considering offer of £%d for %s (from %s) [%f]' % [ player.name, amount, property.name, proposer.name, ( factors.values.collect{ |f| ( 100 / factors.count ) * f }.inject(:+) / 100 ) ]
		property.sell_to(proposer, amount) if Random.rand(1..100) > ( factors.values.collect{ |f| ( 100 / factors.count ) * f }.inject(:+) / 100 )
	}
}