note
	description: "[
		Root class for all the locations (ports, sea-areas, bases) in VITP.
		]"
	author: "Jimmy J. Johnson"

deferred class
	LOCATION

inherit

	VITP_ITEM
		redefine
			make
		end

feature {NONE} -- Initialization

	make (a_game: like game)
			-- Initialize Current
		do
			Precursor (a_game)
--			create defining_position
			create units_imp.make
			is_stable := True
--			defining_cell := game.
		end

feature -- Access

	defining_position: TUPLE [x, y: INTEGER_32]
			-- The x- and y-coordinate (in millimeters) of Current's
			-- position relative to the top-left corner of the board.
		deferred
		end

	defining_cell: VITP_CELL
			-- The "central" cell for Current, around which its
			-- positioning `grid' is built.
		local
			x, y: INTEGER_32
		once
			x := ((defining_position.x + game.board_left) / game.cell_size).truncated_to_integer + 1
			y := ((defining_position.y + game.board_top) / game.cell_size).truncated_to_integer + 1
			Result := game.cell (x, y)
		end

	units: LINKED_SET [like unit_anchor]
			-- Copy of the list of units in current.
			-- Why do I have this feature?
		do
			print ("LOCATION.units:  why have this feature? %N");
			Result := units_imp.twin
		end

	japanese_units: LINKED_SET [like unit_anchor]
			-- All the japanese units in Current
		do
			create Result.make
			from units_imp.start
			until units_imp.exhausted
			loop
				if units_imp.item.nationality = game.Japanese then
					Result.extend (units_imp.item)
				end
				units_imp.forth
			end
		end

	allied_units: LINKED_SET [like unit_anchor]
			-- All the allied units in Current
		do
			create Result.make
			from units_imp.start
			until units_imp.exhausted
			loop
				if units_imp.item.nationality /= game.Japanese then
					Result.extend (units_imp.item)
				end
				units_imp.forth
			end
		end

	adjacent_sea_areas: LINEAR [SEA_AREA]
			-- A list of all sea areas that touch this location
		deferred
		end

feature -- Status report

	is_port: BOOLEAN
			-- Is the location a {PORT}?
		do
			Result := Current.conforms_to ({PORT})
		end

	is_sea_area: BOOLEAN
			-- Is the location a {SEA_AREA}?
		do
			Result := Current.conforms_to ({SEA_AREA})
		end

feature -- Basic operations

	put (a_unit: like unit_anchor)
			-- Ensure `a_unit' is in Current
		require
			unit_exists: a_unit /= Void
--			valid_move: a_unit.is_valid_move (Current)
		do
			is_stable := False
			units_imp.put (a_unit)
			if a_unit.location /= Current then
				a_unit.set_location (Current)
			end
			is_stable := True
		ensure
			has_unit: has (a_unit)
			location_integrity: a_unit.location = Current
		end

	prune (a_unit: like unit_anchor)
			-- Ensure `a_unit' is NOT in Current
		require
			unit_exists: a_unit /= Void
		do
			is_stable := False
			if has (a_unit) then
				units_imp.prune (a_unit)
			end
			is_stable := True
		ensure
			not_has_unit: not has (a_unit)
		end

feature -- Query

--	friendly_ports (a_nationality: NATIONALITY): LINKED_SET [PORT]
--			-- Of the `adjoining_ports' the ones that are friendly to `a_nationality'
--		local
--			p: like adjoining_ports
--		do
--			create Result.make
--			from ports.start
--			until ports.exhausted
--			loop
--				if not ports.item.is_enemy_controlled (a_nationality) then
--					Result.extend (ports.item)
--				end
--				ports.forth
--			end
--		end

	distance_to (other: LOCATION): INTEGER
			-- The distance between Current and `other'
		do
			io.put_string ("LOCATION.distance_to:  Fix me - move functionality to VITP_GAME? %N")
			Result := {INTEGER_32}.max_value
		end

	is_enemy_controlled (a_nationality: like game.japanese): BOOLEAN
			-- Is the location controlled by the other side?
		do
			Result := (game.is_allied_nationality (a_nationality) and not game.is_allied_nationality (nationality)) or
						(not game.is_allied_nationality (a_nationality) and game.is_allied_nationality (nationality))
		end

	has (a_unit: like unit_anchor): BOOLEAN
			-- Does Current contain `a_unit'?
		require
			unit_exists: a_unit /= Void
		do
			Result := units_imp.has (a_unit)
		end

	has_allied: BOOLEAN
			-- Does this location have any allied game piece here?
		local
			u: like unit_anchor
		do
			from units_imp.start
			until Result or else units_imp.after
			loop
				u := units_imp.item
				Result := game.is_allied_nationality (u.nationality)
				units_imp.forth
			end
		end

	has_japanese: BOOLEAN
			-- Does this location have any japanese game piece here?
		local
			u: like unit_anchor
		do
			from units_imp.start
			until Result or else units_imp.after
			loop
				u := units_imp.item
				Result := not game.is_allied_nationality (u.nationality)
				units_imp.forth
			end
		end

	has_japanese_patroller: BOOLEAN
			-- Does this location contain at least one Japanese patroller?
		local
			u: like unit_anchor
		do
			from units_imp.start
			until Result or else units_imp.after
			loop
				u := units_imp.item
				Result := u.is_patrolling and then
							not game.is_allied_nationality (u.nationality)
				units_imp.forth
			end
		end

	has_allied_patroller: BOOLEAN
			-- Does this location contain at least one Japanese patroller?
		local
			u: like unit_anchor
		do
			from units_imp.start
			until Result or else units_imp.after
			loop
				u := units_imp.item
				Result := u.is_patrolling and then
							game.is_allied_nationality (u.nationality)
				units_imp.forth
			end
		end

	has_japanese_air_raiders: BOOLEAN
			-- Does Current contain any Japanese carriers?
			-- (Carriers are the only units that can air raid.)
		local
			set: like japanese_units
		do
			set := japanese_units
			from set.start
			until set.exhausted or Result
			loop
				Result := attached {SHIP} set.item as s and then s.airstrike_factor > 0
				set.forth
			end
		end

	has_allied_air_raiders: BOOLEAN
			-- Does Current contain any Japanese carriers?
			-- (Carriers are the only units that can air raid.)
		local
			set: like allied_units
		do
			set := allied_units
			from set.start
			until set.exhausted or Result
			loop
				Result := attached {SHIP} set.item as s and then s.airstrike_factor > 0
				set.forth
			end
		end

	has_allied_amphibious: BOOLEAN
			-- Does Current contain any Allied amphibious units?
		local
			set: like allied_units
		do
			set := allied_units
			from set.start
			until set.exhausted or Result
			loop
				Result := attached {AMPHIBIOUS_UNIT} set.item
				set.forth
			end
		end

	has_japanese_amphibious: BOOLEAN
			-- Does Current contain any Japanese amphibious units?
		local
			set: like japanese_units
		do
			set := japanese_units
			from set.start
			until set.exhausted or Result
			loop
				Result := attached {AMPHIBIOUS_UNIT} set.item
				set.forth
			end
		end

feature {NONE} -- Implementation

	units_imp: LINKED_SET [like unit_anchor]
			-- The units that are in this location

	has_invalid_unit: BOOLEAN
			-- Does Current contain a unit that does not refer back to Current?
			-- For invariant checking
			-- Should always be false
		require
			call_only_when_stable: is_stable
		do
			from units_imp.start
			until Result or units_imp.exhausted
			loop
				Result := units_imp.item.location /= Current
				units_imp.forth
			end
		end

	is_stable: BOOLEAN
			-- Set to false when pruning and adding units for invariant checking
			-- of referential integrity between units and locations

feature {NONE} -- Anchors (for covariant redefinitions)

	unit_anchor: ATTACK_UNIT
			-- Anchor for features using units.
			-- Not to be called; just used to anchor types.
			-- Declared as a feature to avoid adding an attribute.
		require
			not_callable: False
		do
			check
				do_not_call: False then
					-- Because give no info; simply used as anchor.
			end
		end

invariant

	valid_controller: nationality = game.japanese or nationality = game.us or nationality = game.nobody

	all_units_imp_refer_to_current: is_stable implies not has_invalid_unit

end
