#!/usr/bin/env ruby
# $Revision: 1.33 $
# $Date: 2003/12/06 18:12:08 $
# $Author: jefus, mikeman2 $

class Mobile < Base
	attr_accessor :connection
	# ability stuff
	attr_accessor :str, :dex, :con, :int, :wil, :per
	attr_accessor :skills

	def initialize(cfile)
		@config = cfile
		@connection = nil
		begin
			@str = Ability.new(@config['@str'])
			@dex = Ability.new(@config['@dex'])
			@con = Ability.new(@config['@con'])
			@int = Ability.new(@config['@int'])
			@wil = Ability.new(@config['@wil'])
			@per = Ability.new(@config['@per'])
			if @config['@access'] != nil
				@access = @config['@access'].to_i
			else
				@access = 0
			end
		rescue
			Logger.log("Mobile#initialize: #{$!}")
		end
		#p @str
		@skills = {}
		super(@config)
	end
	
	def write(string)
		if @connection
			@connection.write(string)
		end
	end

	def puts(line)
		if @connection
			@connection.puts(line.gsub(/\n/, "\n\r"))
		end
	end

	def gets
		if @connection
			return @connection.gets
		end
	end

	def save
		self.instance_attributes.each{|key, value|
			if value.instance_of?(Ability)
				#Logger.log("saving ability #{key}")
				@config[key] = value.to_s
			end
		}
		@config['@access'] = @access
		super
	end
	def checkSkill(name, modifier = 0) # average situation modifier by default
		if skill = Skill[name]
			ordinary = getSkillScore(skill, Skill.Ordinary)
			good     = getSkillScore(skill, Skill.Good)
			amazing  = getSkillScore(skill, Skill.Amazing)
			if ordinary and good and amazing # make sure nothing is nil
				control = Dice.control
				situation = Dice.situation(modifier)
				result = control + situation

				puts("Rolling for #{skill.name}...")
				puts("Control: #{control}\tSituation: #{situation}\tResult: #{result}")
				if result <= amazing
					puts("&GAmazing success!&*")
					return Skill.Amazing
				elsif result <= good
					puts("&gGood success!&*")
					return Skill.Good
				elsif result <= ordinary
					puts("Ordinary success.&*")
					return Skill.Ordinary
				elsif control == 20
					puts("&RCritical failure!&*")
					return Skill.CriticalFailure
				else
					if control == 1 # a 1 turns a failure into an ordinary success
						puts("Ordinary success. (automatic success)")
						return Skill.Ordinary
					else
						puts("&rFailure!&*")
						return Skill.Failure
					end
				end
			else
				Logger.log("No such skill '#{name}'.") # these no such skill messages
																							 # should be Logger.errors or etc.
			end
		end
	end

	def move(where)
		@location.puts("#{@name} leaves the room.", self) if @location
		super(where)
		@location.puts("#{@name} enters the room.", self)
	end

	def gainSkill(name, rank = 1) # improve by 1 rank by default
		if skill = Skill[name]
			if skill.broad? # broad skills don't have ranks
				if @skills.include?(skill) # already have it... can't do anything.
					Logger.log("gainSkill: #{self} already has skill '#{name}'.")
				else
					@skills[skill] = 0
					puts("You learn the broad skill '#{name}'.")
				end
			else # but specialty skills do
				if @skills.include?(skill) # already have it... improve by rank
					@skills[skill] = @skills[skill] + rank
					puts("You improve in '#{name}' to rank #{@skills[skill]}.")
				else # learn from scratch
					@skills[skill] = rank
					puts("You learn the specialty skill '#{name}' at rank #{rank}.")
				end
			end
		else
			Logger.log("No such skill '#{name}'.")
		end
	end

	# returns an ordinary, good, or amazing score for a specified skill
	def getSkillScore(name, rating = Skill.Ordinary)
		# sanity check?
		if rating < Skill.Ordinary or rating > Skill.Amazing
			Logger.log("getSkillScore: invalid rating")
			return nil
		end

		# name can actually be either a skill name or a skill object
		if name.is_a?(String)
			skill = Skill[name]
		else # it should already be a skill object, then
			skill = name
		end
		
		if skill
			ability = eval("@#{skill.ability}") # "str" -> @str
			if @skills.include?(skill) # first of all, do we know the skill?
				rank = @skills[skill]
				if skill.broad? # broad skills have no rank, and score == ability
					case rating
					when Skill.Ordinary
						return ability.to_i
					when Skill.Good
						return ability / 2
					when Skill.Amazing
						return ability / 4
					end
				else # specialty skill scores == rank + ability
					case rating
					when Skill.Ordinary
						return ability + rank
					when Skill.Good
						return (ability + rank) / 2
					when Skill.Amazing
						return (ability + rank) / 4
					end
				end
			else # we don't have the skill
				if skill.broad? # if it's a broad skill, we use its untrained ability
					case rating
					when Skill.Ordinary
						return ability.untrained
					when Skill.Good
						return ability.untrained / 2
					when Skill.Amazing
						return ability.untrained / 4
					end
				else
					# first check to see if the specialty skill can be used untrained
					if skill.untrained?
						# untrained specialty skill checks use the broad skill score
						# i feel like i'm repeating code here, but oh well.
						case rating
						when Skill.Ordinary
							return ability.to_i
						when Skill.Good
							return ability / 2
						when Skill.Amazing
							return ability / 4
						end
					else
						return nil # skill can't be used untrained
					end
				end
			end
		end
	end

        def enterGame(new = false)
                move(@location)
                if new # special case for new players
                        @str = Ability.new(10)
                        @dex = Ability.new(10)
                        @con = Ability.new(10)
                        @int = Ability.new(10)
                        @wil = Ability.new(10)
                        @per = Ability.new(10)
                end
        end

end

Logger.log("Mobile code initialized.")