19928/jj_vitp/Implementation/classes/units/attack_unit.e
Jocelyn Fiat 6dde6425c2 init
2024-06-17 09:09:33 +02:00

1105 lines
32 KiB
Plaintext

note
description: "[
Root class for all the game pieces in VITP.
]"
author: "Jimmy J. Johnson"
deferred class
ATTACK_UNIT
inherit
VITP_ITEM
redefine
make
end
COMPARABLE
undefine
copy,
is_equal
end
feature -- Initialization
make (a_game: like game)
-- Initialize with the values; these are initial values and cannot be changed
-- `a_name' = name of the ship or unit
-- `a_nationality' = country to which it belongs
-- `a_arrival_turn' = turn 1 to 9 in which the unit enters the game
-- `a_airstrike' = the unit's "airstrike factor"
-- `a_guns' = the unit's "gunnery factor"
-- `a_armor' = the unit's "armor factor"
-- `a_speed' = the unit's "speed factor"
-- `a_bonus' = true if the unit has an initial attack bonus
local
lin: LINEAR [PORT]
do
Precursor {VITP_ITEM} (a_game)
create task_force.make (a_game)
task_force.set_ordered
-- arrival_location := game.still_in_box
position := [0, 0]
-- Initialize to never return (changed for air and amphibious units)
returning_turn := 0
task_force.extend (Current)
end
feature -- Access
arrival_turn: INTEGER
-- Turn on which this unit enters the game.
deferred
end
airstrike_factor: INTEGER
-- The initial number of dice the unit rolls when attacking
-- during a "day action".
deferred
end
gunnery_factor: INTEGER
-- The initial value for the number of dice the unit rolls
-- when attacking during a "night action".
deferred
end
defense_factor: INTEGER
-- The number of damage points a unit can have without sinking.
-- (This is doubled when the unit is in port.)
deferred
end
speed_factor: INTEGER
-- The initial "speed" of the unit.
deferred
end
attack_bonus: BOOLEAN
-- The initial setting saying if a unit can add one to each die roll.
-- If the unit is a carrier this applies only to the airstrike factor.
deferred
end
returning_turn: INTEGER
-- The turn on which this unit can reenter the game.
home_port: PORT
-- The {PORT} from which Current is basing this turn.
attribute
Result := game.default_port
end
location: LOCATION
-- The sea, base, or port at which Current is located.
attribute
-- Result := game.still_in_box
if Current.is_japanese then
Result := game.japanese_oa_chart
else
if Current.arrival_turn = 1 then
Result := game.allied_starting_forces_chart
else
Result := game.allied_oa_chart
end
end
end
damage: INTEGER
-- The amount of total damage Current has taken
gunnery_count: INTEGER
-- Number of dice the unit rolls when attacking during a "night action".
-- It is the `Gunnery_factor' reduced by the amount of `damage'.
do
Result := (gunnery_factor - damage).max (1)
end
defense_count: INTEGER
-- The amount of armor remaining, used to determine if a unit is "sunk".
do
Result := defense_factor - damage
end
speed_count: INTEGER
-- The actual speed of Current calculated from other factors
do
Result := (speed_factor - damage).max (1)
end
airstrike_count: INTEGER
-- Number of dice the unit rolls when attacking during a "day actions".
do
Result := airstrike_factor
end
task_force: TASK_FORCE
-- The whole force including Current if others
target: ATTACK_UNIT
-- The target (if `is_targetting')
do
check attached target_imp as t then
Result := t
end
end
relative_value: INTEGER
-- Relative value of current to other units, calculated from the
-- current values of the gunnery, defense, and speed counts.
local
b_fac: INTEGER
do
if attack_bonus then
if airstrike_factor > 0 then
-- Apply bonus to airstrike only
b_fac := Bonus_weight * airstrike_weight
-- Result := (airstrike_count + Bonus_weight) * Airstrike_weight
-- Result := Result + gunnery_count * Gunnery_weight
else
-- apply bonus to guns unless too much damage
if defense_count > 0 then
b_fac := Bonus_weight * Gunnery_weight
-- Result := (gunnery_count + Bonus_weight) * Gunnery_weight
-- Result := Result + airstrike_count * Airstrike_weight
end
end
end
Result := b_fac + airstrike_count + gunnery_count
Result := Result + defense_count * Defense_weight + speed_factor * Speed_weight
-- if Current = Tone then
-- do_nothing
-- end
-- if Current = Mutsu then
-- do_nothing
-- end
end
patrol_distance: INTEGER
-- How may sea areas can Current move through as patroller?
-- Determined by the unit type and nationality
do
Result := 2
end
raid_distance: INTEGER
-- How many sea areas can Current move through as raider?
-- Determined by the unit type and nationality
local
has_non_major: BOOLEAN
do
if is_task_force then
from task_force.start
until task_force.exhausted or has_non_major
loop
if not task_force.item.is_major_power then
has_non_major := true
end
task_force.forth
end
end
if not has_non_major then
Result := patrol_distance + 1
end
end
feature -- Access
sailing_distance: INTEGER
-- The distance Current can patrol or raid (depending on `is_raiding').
-- This is the minimum of all contained units.
local
f: INTEGER
u: ATTACK_UNIT
do
Result := {INTEGER}.Max_value
from task_force.start
until task_force.is_after
loop
u := task_force.item
if u.sailing_distance < Result then
Result := f
end
task_force.forth
end
end
reinforceable_ports: LINKED_SET [PORT]
-- A list containing each {PORT} to which Current
-- can be moved during the reinforcement step.
require
is_reinforcing: game.sequence_of_play.is_reinforcement_step
deferred
end
patrolable_sea_areas: LINKED_SET [SEA_AREA]
-- A list containing each {SEA_AREA} to which Current
-- can be moved during the moving patrollers step.
local
sop: VITP_SEQUENCE_OF_PLAY
sd: INTEGER
s: SEA_AREA
dist: INTEGER
do
-- io.put_string ("ATTCK_UNIT.patrolable_sea_areas: fix using GRAPH_ITERATOR.shortest_paths %N")
create Result.make
sop := game.sequence_of_play
if sop.is_patrolling_step and
((not game.is_allied_nationality (nationality) and then sop.is_japanese_player) or else
(game.is_allied_nationality (nationality) and then sop.is_allied_player)) then
if home_port = game.yokosuka_navy_yard or home_port = game.okinawa then
Result.extend (game.japanese_islands)
if not is_opposed (game.japanese_islands) then
Result.extend (game.indonesia)
Result.extend (game.marianas_islands)
Result.extend (game.central_pacific_ocean)
Result.extend (game.aleutian_islands)
end
elseif home_port = game.saigon or home_port = game.singapore then
Result.extend (game.indonesia)
if not is_opposed (game.indonesia) then
Result.extend (game.bay_of_bengal)
Result.extend (game.indian_ocean)
Result.extend (game.south_pacific_ocean)
Result.extend (game.marianas_islands)
Result.extend (game.japanese_islands)
end
elseif home_port = game.ceylon or home_port = game.andaman_islands then
Result.extend (game.bay_of_Bengal)
if not is_opposed (game.bay_of_bengal) then
Result.extend (game.indonesia)
Result.extend (game.indian_ocean)
end
elseif home_port = game.philippines then
Result.extend (game.indonesia)
Result.extend (game.marianas_Islands)
if not is_opposed (game.indonesia) then
Result.extend (game.bay_of_bengal)
Result.extend (game.indian_ocean)
Result.extend (game.south_pacific_ocean)
Result.extend (game.marianas_islands)
Result.extend (game.japanese_islands)
end
if not is_opposed (game.marianas_islands) then
Result.extend (game.south_pacific_ocean)
Result.extend (game.marshall_islands)
Result.extend (game.central_pacific_ocean)
Result.extend (game.japanese_islands)
end
elseif home_port = game.lae then
Result.extend (game.south_pacific_ocean)
Result.extend (game.indonesia)
if not is_opposed (game.indonesia) then
Result.extend (game.japanese_islands)
Result.extend (game.marianas_islands)
end
if not is_opposed (game.south_pacific_ocean) then
Result.extend (game.marianas_islands)
Result.extend (game.coral_sea)
Result.extend (game.us_mandate)
Result.extend (game.marshall_islands)
end
elseif home_port = game.australia or home_port = game.port_moresby then
Result.extend (game.indian_ocean)
Result.extend (game.coral_sea)
if not is_opposed (game.indian_ocean) then
Result.extend (game.bay_of_bengal)
Result.extend (game.indonesia)
end
if not is_opposed (game.coral_sea) then
Result.extend (game.south_pacific_ocean)
Result.extend (game.us_mandate)
end
elseif home_port = game.guadalcanal then
Result.extend (game.coral_sea)
Result.extend (game.south_pacific_ocean)
if not is_opposed (game.coral_sea) then
Result.extend (game.indian_ocean)
Result.extend (game.us_mandate)
end
if not is_opposed (game.south_pacific_ocean) then
Result.extend (game.indonesia)
Result.extend (game.marianas_islands)
Result.extend (game.marshall_islands)
Result.extend (game.us_mandate)
end
elseif home_port = game.new_hebrides then
Result.extend (game.coral_sea)
Result.extend (game.us_mandate)
if not is_opposed (game.coral_sea) then
Result.extend (game.indian_ocean)
Result.extend (game.south_pacific_ocean)
end
if not is_opposed (game.us_mandate) then
Result.extend (game.south_pacific_ocean)
Result.extend (game.marshall_islands)
Result.extend (game.hawaiian_islands)
end
elseif home_port = game.samoa then
Result.extend (game.us_mandate)
if not is_opposed (game.us_mandate) then
Result.extend (game.coral_sea)
Result.extend (game.south_pacific_ocean)
Result.extend (game.marshall_islands)
Result.extend (game.hawaiian_islands)
end
elseif home_port = game.johnston_island or home_port = game.pearl_harbor then
Result.extend (game.hawaiian_islands)
if not not is_opposed (game.hawaiian_Islands) then
Result.extend (game.us_mandate)
Result.extend (game.marshall_islands)
Result.extend (game.central_pacific_ocean)
Result.extend (game.north_pacific_ocean)
end
elseif home_port = game.kwajalein or home_port = game.maloelap then
Result.extend (game.marshall_islands)
if not is_opposed (game.marshall_islands) then
Result.extend (game.south_pacific_ocean)
Result.extend (game.us_mandate)
Result.extend (game.hawaiian_islands)
Result.extend (game.central_pacific_ocean)
Result.extend (game.marianas_islands)
end
elseif home_port = game.truk then
Result.extend (game.south_pacific_ocean)
Result.extend (game.marshall_islands)
Result.extend (game.marianas_islands)
if not is_opposed (game.south_pacific_ocean) then
Result.extend (game.indonesia)
Result.extend (game.coral_sea)
Result.extend (game.us_mandate)
end
if not is_opposed (game.marshall_islands) then
Result.extend (game.us_mandate)
Result.extend (game.hawaiian_islands)
Result.extend (game.central_pacific_ocean)
end
if not is_opposed (game.marianas_islands) then
Result.extend (game.indonesia)
Result.extend (game.japanese_islands)
Result.extend (game.central_pacific_ocean)
end
elseif home_port = game.saipan then
Result.extend (game.marianas_islands)
if not is_opposed (game.marianas_islands) then
Result.extend (game.japanese_Islands)
Result.extend (game.indonesia)
Result.extend (game.south_pacific_ocean)
Result.extend (game.marshall_islands)
Result.extend (game.central_pacific_ocean)
end
elseif home_port = game.midway then
Result.extend (game.central_pacific_ocean)
if not is_opposed (game.central_pacific_ocean) then
Result.extend (game.japanese_islands)
Result.extend (game.marianas_islands)
Result.extend (game.marshall_islands)
Result.extend (game.hawaiian_islands)
Result.extend (game.north_pacific_ocean)
Result.extend (game.aleutian_islands)
end
elseif home_port = game.dutch_harbor then
Result.extend (game.north_pacific_ocean)
Result.extend (game.aleutian_islands)
if not is_opposed (game.north_pacific_ocean) then
Result.extend (game.central_pacific_ocean)
Result.extend (game.hawaiian_islands)
end
if not is_opposed (game.aleutian_islands) then
Result.extend (game.japanese_islands)
Result.extend (game.central_pacific_ocean)
end
elseif home_port = game.attu then
Result.extend (game.aleutian_islands)
if not is_opposed (game.aleutian_islands) then
Result.extend (game.japanese_islands)
Result.extend (game.central_pacific_ocean)
Result.extend (game.north_pacific_ocean)
end
else
end
end
end
landable_ports: LINKED_SET [PORT]
-- A list containing each {PORT} at which Current can make
-- a landing if at the appropriate point in the game
local
lin: LINEAR [PORT]
do
create Result.make
if attached {SEA_AREA} location as s then
lin := s.adjoining_ports
from lin.start
until lin.exhausted
loop
if not lin.item.is_enemy_controlled (nationality) then
Result.extend (lin.item)
end
lin.forth
end
end
-- Add all major ports to the set
from game.major_ports.start
until game.major_ports.after
loop
if not game.major_ports.item_for_iteration.is_enemy_controlled (nationality) then
Result.extend (game.major_ports.item_for_iteration)
end
game.major_ports.forth
end
end
arrivable_locations: LINKED_LIST [LOCATION]
-- The possible locations to which Current can move when
-- coming into [or back into] the game
local
sop: VITP_SEQUENCE_OF_PLAY
do
create Result.make
sop := game.sequence_of_play
if arrival_turn = sop.turn or returning_turn = sop.turn then
if nationality = sop.nationality then
if nationality = game.japanese then
end
end
end
end
arrival_location: LOCATION
-- The port or sea area at which this unit may enter the game
do
if nationality = game.japanese and game.yokosuka_navy_yard.nationality = game.japanese then
Result := game.yokosuka_navy_yard
elseif nationality = game.us then
if game.pearl_harbor.nationality = game.us then
Result := game.pearl_harbor
elseif game.samoa.nationality = game.us then
Result := game.samoa
else
io.put_string ("ATTACK_UNIT.arrival_location -- put it on US_chart. %N")
Result := game.still_in_box
end
elseif nationality = game.british and game.ceylon.nationality = game.us then
Result := game.ceylon
elseif nationality = game.australian then
Result := game.australia
else
Result := game.still_in_box
check
should_not_happpen: False
-- because all nationalities have been checked
end
end
end
arrival_port: like home_port
-- The port to which Current is assigned when it comes into
-- the game during a reinforcement action.
do
Result := game.default_port
if nationality = game.japanese and game.yokosuka_navy_yard.nationality = game.japanese then
Result := game.yokosuka_navy_yard
elseif nationality = game.us then
if game.pearl_harbor.nationality = game.us then
Result := game.pearl_harbor
else
Result := game.samoa
end
elseif nationality = game.british then
if Current = game.victorious and game.pearl_harbor.nationality = game.us then
Result := game.pearl_harbor
elseif game.ceylon.nationality = game.us then
Result := game.ceylon
end
elseif nationality = game.australian then
Result := game.australia
else
check
should_not_happpen: False
-- because all nationalities have been checked
end
end
end
arrival_position: like position
-- The location (latitude/longitude-like coordinates) where Current will enter the game
do
-- The following measurements in millimeters were taken from the game board
if arrival_location = game.Yokosuka_navy_yard then
Result := [300, 140]
elseif arrival_location = game.Pearl_Harbor then
Result := [700, 330]
elseif arrival_location = game.Samoa then
Result := [570, 480]
elseif arrival_location = game.Ceylon then
Result := [185, 15]
elseif arrival_location = game.Bay_of_Bengal then
Result := [10, 370]
elseif arrival_location = game.Indonesia then
Result := [130, 350]
elseif arrival_location = game.Philippines then
Result := [210, 270]
elseif arrival_location = game.Australia then
Result := [240, 470]
elseif arrival_location = game.Singapore then
Result := [90, 280]
elseif arrival_location = game.Coral_sea then
Result := [370, 520]
elseif arrival_location = game.US_mandate then
Result := [500, 500]
elseif arrival_location = game.Hawaiian_islands then
Result := [570, 380]
else
-- Return its Current position
Result := [position.longitude, position.latitude]
end
end
feature -- Element change
set_location (a_location: LOCATION)
-- Move all ships in `task_force' to `a_location'
require
is_valid_move: is_valid_move (a_location)
local
u: ATTACK_UNIT
do
io.put_string ("ATTACK_UNIT.set_location: " + name.out + " to " + a_location.name + "%N")
from task_force.start
until task_force.is_after
loop
u := task_force.item
u.set_location_internal (a_location)
task_force.forth
end
ensure
location_set: location = a_location
location_set_for_all:
end
set_home_port (a_port: PORT)
-- Change the unit's `home_port'
require
is_valid_base: is_valid_unit_move (a_port)
do
home_port := a_port
end
set_returning_turn (a_turn: INTEGER)
-- Set the turn on which Current can reenter the game
require
valid_turn: a_turn >= 3 and a_turn <= 9
do
returning_turn := a_turn
end
set_location_internal (a_location: LOCATION)
-- Used internally to bypass referential invariant checking
do
if location /= a_location then
is_stable := False
location.prune (Current)
location := a_location
if not a_location.has (Current) then
a_location.put (Current)
end
is_stable := True
end
end
set_target (a_target: ATTACK_UNIT)
-- Get ready to attack `a_target'
require
same_locations: location = a_target.location
do
target_imp := a_target
end
remove_target
-- Remove any target from Current sights
do
target_imp := Void
end
feature -- Query
is_valid_move (a_location: LOCATION): BOOLEAN
-- Can this {TASK_FORCE} (all units) move to `a_location'?
do
Result := True
from task_force.start
until task_force.is_after or not Result
loop
Result := task_force.item.is_valid_unit_move (a_location)
task_force.forth
end
end
is_valid_unit_move (a_location: LOCATION): BOOLEAN
-- Can Current (regardless of any other units that
-- may be in the `task_force') move to `a_location'?
do
io.put_string ("{ATTACK_UNIT}.is_valid_unit_move: fix to for restricted port %N")
Result := True
end
feature -- Access
position: VITP_POSITION
-- The position in millimeters (east/west and up/down) from the
-- top-left of the [logical] VITP world. That is, the position
-- of an attack unit is relative to the top-left corner of the
-- game board which is at point (0, 0).
unit_size: INTEGER
-- The size of Current (square).
-- Assume it is `Ship_size' and redefine for {AIR_UNIT} and
-- for {AMPHIBIOUS_UNIT}.
once
Result := game.initial_ship_size
end
corners: ARRAY [VITP_POSITION]
-- The four corner points of Current (square ships) calculated
-- from Current's location and `unit_size', starting at the top/
-- left and going clockwise.
local
p: VITP_POSITION
h: INTEGER
do
h := unit_size // 2
create Result.make_filled (create {VITP_POSITION}, 1, 4)
create p.set_xy (position.longitude - h, position.latitude - h)
Result.put (p, 1)
create p.set_xy (position.longitude + h, position.latitude - h)
Result.put (p, 2)
create p.set_xy (position.longitude + unit_size, position.latitude + h)
Result.put (p, 3)
create p.set_xy (position.longitude - unit_size, position.latitude + unit_size)
Result.put (p, 4)
end
feature -- Element change
set_position (a_position: like position)
-- Change the `position' of Current [and all units in `task_force']
require
position_exists: a_position /= Void
is_valid_position: not is_incompatible_position (a_position)
local
u: ATTACK_UNIT
do
from task_force.start
until task_force.is_after
loop
u := task_force.item
u.internal_set_position (a_position)
task_force.forth
end
ensure
position_set: position ~ a_position
end
feature -- Query
-- is_valid_position (a_position: VITP_POSITION): BOOLEAN
-- -- Is `a_position' valid? Yes if the position is on the board/table,
-- -- (garanteed by invariant of {VITP_POSITION}), not on an enemy unit,
-- -- and not on a unit of the wrong type (i.e. a submarine cannot join
-- -- a task force.)
-- do
-- Result := not is_on_incompatible_unit (a_position)
-- end
is_incompatible_position (a_position: VITP_POSITION): BOOLEAN
-- Yes if repositioning Current to `a_position' would cause Current
-- to overlap a unit that is incompatible for a `join_force' (e.g.
-- on a submarine or on an enemy)?
deferred
end
contains_position (a_position: VITP_POSITION): BOOLEAN
-- Is `a_position' on or in Current?
-- This feature uses a ray-casting algorithm which determines if the
-- number of edge crossings made by a ray to the right is odd (inside)
-- or even (outside).
local
pts: like corners
i, j: INTEGER
do
pts := corners
from
i := 1
j := 4
until i > 4
loop
-- Get integer values so algorithm can work.
-- if ( ((pts[i] >= a_position) /= (pts[j] >= a_position)) and
-- (a_position <= (pts[j] - pts[i]) *
-- (a_position - pts[i]) //
-- (pts[j] - pts[i]) + pts[i]) ) then
-- -- Invert Result every time an edge is crossed.
-- Result := not Result
-- end
j := i
i := i + 1
end
end
overlaps (a_other: ATTACK_UNIT): BOOLEAN
-- Does Current occupy any space occupied by a_other
local
pts: like corners
i: INTEGER
do
if Current /= a_other then
pts := corners
from i := 1
until i > pts.count or Result
loop
Result := a_other.contains_position (pts[i])
i := i + 1
end
-- Check the other way around
if not Result then
pts := a_other.corners
from i := 1
until i > pts.count or Result
loop
Result := contains_position (pts[i])
i := i + 1
end
end
end
end
-- is_same_power (a_nationality: NATIONALITY): BOOLEAN
-- -- Is Current the same power (Axis or Allied) as `a_natinality'?
-- do
-- Result := (nationality.is_allied and a_nationality.is_allied) or else
-- (not nationality.is_allied and not a_nationality.is_allied)
-- end
feature -- Basic operations
join_force (a_other: ATTACK_UNIT)
-- Join forces with `a_other' as a single `task_force'
require
not_submarine: not attached {SUBMARINE} a_other and not attached {SUBMARINE} Current
lba_implication: attached {AIR_UNIT} task_force.first implies attached {AIR_UNIT} a_other
other_lba_implication: attached {AIR_UNIT} a_other implies attached {AIR_UNIT} task_force.first
not_lba_implication: not attached {AIR_UNIT} task_force.first implies not attached {AIR_UNIT} a_other
not_other_lba_implication: not attached {AIR_UNIT} a_other implies not attached {AIR_UNIT} task_force.first
not_same_units: not (a_other = Current)
not_same_task_forces: (is_task_force and a_other.is_task_force) implies
not (task_force = a_other.task_force)
not_opposing_sides: not is_opposed (a_other)
same_location: location = a_other.location
local
u: ATTACK_UNIT
pos: VITP_POSITION
do
is_stable := False
-- Put all units into `a_other's `task_force'
pos := a_other.position
from task_force.start
until task_force.is_after
loop
u := task_force.item
-- u.position.set_xy (pos.longitude, pos.latitude)
a_other.task_force.extend (u)
task_force.forth
end
-- Remove all the units from Current's `task_force'
task_force.wipe_out
-- Make to two tasks forces the same one
set_task_force (a_other.task_force)
is_stable := True
ensure
same_task_forces: task_force = a_other.task_force
has_multiple_units: task_force.count >= 2
end
leave_force
-- Remove Current from the `task_force' to which it belongs, but only
-- if there are other ships in the force, and put it in its own.
require
is_in_task_force: is_task_force
local
u: ATTACK_UNIT
do
task_force.prune (Current)
create task_force.make (game)
task_force.extend (Current)
ensure
not_in_force: not is_task_force
end
feature -- Status report
is_task_force: BOOLEAN
-- Is this unit part of a task force?
do
Result := task_force.count > 1
ensure
result_implies_in_force: task_force.has (Current)
result_implies_others: Result implies task_force.count >= 2
end
is_in_game: BOOLEAN
-- Is this unit in the game? (I.e. not sunk, not still to enter)
do
Result := is_at_sea or is_in_port or
location = game.uncommitted_japanese_location or
location = game.uncommitted_allied_location
end
is_at_sea: BOOLEAN
-- Is this unit at sea?
do
Result := attached {SEA_AREA} location
end
is_in_port: BOOLEAN
-- Is this unit in port?
do
Result := attached {PORT} location
end
is_movable: BOOLEAN
-- Can Current move (to sea or back to port) at
-- this time in the game?
local
u: ATTACK_UNIT
do
Result := true
from task_force.start
until task_force.is_after or not Result
loop
u := task_force.item
Result := u.internal_is_movable
task_force.forth
end
end
internal_is_movable: BOOLEAN
-- Can Current move (not the whole `task_force') move at this time?
local
sop: VITP_SEQUENCE_OF_PLAY
do
sop := game.sequence_of_play
print ("ATTACK_UNIT.internal_is_movable: %N")
print (" sop.is_allied_player = " + sop.is_allied_player.out + "%N")
print (" " + name + ".is_allied = " + is_allied.out + "%N")
print (" sop.is_japaneses_player = " + sop.is_japanese_player.out + "%N")
print (" " + name + ".is_japanese = " + is_japanese.out + "%N")
print (" sop.is_patrolling_step = " + sop.is_patrolling_step.out + "%N")
print (" " + name + ".is_patrolling = " + is_patrolling.out + "%N")
Result := ( (sop.is_allied_player and is_allied) or
(sop.is_japanese_player and is_japanese)) and then
( (sop.is_reinforcement_step and is_returning_unit) or
-- (sop.is_removing_sunk_units_phase and is_sunk) or
-- (sop.is_returning_disabled_units_stage and is_disabled) or
-- (sop.is_removing_sunk_units_phase and is_sunk) or
-- (sop.is_returning_to_port_stage and is_at_sea and not is_sunk) or
(sop.is_patrolling_step and is_patrolling) or
(sop.is_raiding_step and is_raiding))
print (" Result = " + Result.out + "%N")
end
is_stable: BOOLEAN
-- Set to false when pruning and adding for invariant checking
-- of referential integrity between units and locations
is_major_power: BOOLEAN
-- Is Current's `nationality' one of Japanese or US?
do
Result := nationality = game.japanese or nationality = game.us
end
is_sunk: BOOLEAN
-- Has this unit been sunk?
deferred
end
is_bottomed: BOOLEAN
-- Is unit in port with too much damage to sail?
-- Default is Fasle, so redefine for {SHIP}
do
Result := False
ensure
implication: Result implies is_in_port
end
is_disabled: BOOLEAN
-- Is the unit disabled?
is_returning_unit: BOOLEAN
-- Is the unit returning on this turn?
do
Result := returning_turn = game.sequence_of_play.turn
end
is_patrollable: BOOLEAN
-- Can this unit be a patroller for area control purposes?
deferred
end
is_raidable: BOOLEAN
-- Can this unit be a raider?
deferred
end
is_patrolling: BOOLEAN
-- Is this unit a patroller (as opposed to a raider)?
deferred
end
is_raiding: BOOLEAN
-- Is this unit a raider?
deferred
end
feature -- Status setting
set_disabled
-- Mark Current as `is_disabled'
do
is_disabled := True
end
set_not_disabled
-- Mark Current as not `is_disabled'
do
is_disabled := False
end
feature {ATTACK_UNIT} -- Implementation
internal_set_position (a_position: VITP_POSITION)
-- Change the `position' of [only] Current
require
position_exists: a_position /= Void
do
position.set_xy (a_position.longitude, a_position.latitude)
end
feature {ATTACK_UNIT} -- Implementation
feature -- Comparison
is_less alias "<" (other: like Current): BOOLEAN
-- Is current object less than `other'?
do
-- Weight the attack, defense, speed factors and compare result
Result := (relative_value > other.relative_value) or else
(relative_value = other.relative_value and then name < other.name)
-- Result := name < other.name
end
feature {NONE} -- Implementation (weighting factors for `relative_value')
gunnery_weight: INTEGER = 10
defense_weight: INTEGER = 1
speed_weight: INTEGER = 1
airstrike_weight: INTEGER = 10
bonus_weight: INTEGER = 2
feature {ATTACK_UNIT} -- Implementation
set_task_force (a_force: like task_force)
-- Set `task_force' to `a_force'
require
has_current: a_force.has (Current)
do
task_force.prune (Current)
task_force := a_force
ensure
task_force_assigned: task_force = a_force
in_task_force: task_force.has (Current)
end
remove_task_force
-- Remove Current from `task_force' and put it in its own `task_force'
do
task_force.prune (Current)
create task_force.make (game)
end
feature {NONE} -- Implementation (invariant routines)
same_location_for_all: BOOLEAN
-- Do all the unit have the same `location'?
local
c: CURSOR
do
c := task_force.cursor
Result := true
if is_task_force then
from task_force.start
until task_force.is_after
loop
Result := task_force.item.location = location
task_force.forth
end
end
task_force.go_to (c)
end
same_position_for_all: BOOLEAN
-- Do all the units have the same `location'?
local
c: CURSOR
do
c := task_force.cursor
Result := true
if is_task_force then
from task_force.start
until task_force.is_after
loop
Result := task_force.item.position ~ position
task_force.forth
end
end
task_force.go_to (c)
end
feature {NONE} -- Implementation
target_imp: detachable ATTACK_UNIT
-- The unit if any that Current is set to attack
invariant
location_exists: location /= Void
task_force_exists: task_force /= Void
-- longitude_big_enough: position.longitude >= {POSITION_CONSTANTS}.Minimum_longitude
-- longitude_small_enough: position.longitude <= {POSITION_CONSTANTS}.Maximum_longitude
-- latitude_big_enough: position.latitude >= {POSITION_CONSTANTS}.Minimum_latitude
-- latitude_small_enough: position.latitude <= {POSITION_CONSTANTS}.Maximum_latitude
contains_itself: task_force.has (Current)
valid_arrival_turn: arrival_turn >= 1 and arrival_turn <= 9
valid_gunnery_factor: gunnery_factor >= 0 and gunnery_factor <= 9
valid_defense_factor: defense_factor >= 0 and defense_factor <= 9
valid_speed_factor: speed_factor >= 3 and speed_factor <= 9
-- contains_current: task_force.first = Current
-- contains_only_current: task_force.count = 1
location_integrity: is_stable implies location.has (Current)
task_force_integrity: (is_stable and then is_task_force and then task_force.is_stable)
implies task_force.has (Current)
-- task_force_location_implication: is_stable implies (is_task_force implies same_location_for_all)
-- task_force_position_implication: is_stable implies (is_task_force implies same_position_for_all)
end