- Joined
- Jan 11, 2009
- Messages
- 3,414
Alright, i have a ssytem that is designed to simulate trade routes between allied countries in my map. It is meant to work like this:
*Every x seconds, the script groups your allies and sorts them in an array based on how many ports they have. Ally with most ports is 1, ally with second most ports is 2, etc.
*The system groups all your ports and orders the first one in the group to send a trade ship towards the closest port owned by the first ally in the list. The second port will send to the second player in the list, and so on. If there are more ports then allies, it will start over from the top.
*The map is divided into two "theatres", one asian and one european. For this reason, the system has to run once for each theatre to make sure that no ships attempt to cross the border. You will see how this works in the script.
*If a player has no allies with ports in the same theatre, he will not send any trade ships.
Here is the code:
And here is a snippet from the code for capturing ports - not that it is of any interrest:
Here is a shot of the minimap, for better understanding:
Now, my problem is, that some players will not send their ships - Japan and USA both send no ships whatsoever (they spawn, but don't move), while for other players, some individual ports won't send, like Arkhangel'sk, Singapore, etc.
Another problem is that some axis players send ships to allied players, even though they are enemies. For instance, finish port in Petsamo sends ships to russian Murmansk.
The ones that work flawlessly are:
GB Port Morseby to USSR Vladivostok - this trade route functions perfectly.
Chineese port below Changsha to USSR vladivostok - also this works as planned
USSR Vladivostok to US Pearl Harbour - this works well, but since US player won't send ships, they cluster up, and hence the USSR ships can't get past.
GB London to US New York - same as above
All german ports somehow insist on sending their ships to USSR port in Arkhangel'sk, which is unallied
Finnish ports in Petsamo and Oulu both insists on sending ships to unallied USSR port in Murmansk
Please note that this is in the beginning when n ports had been captured. I was playing as USSR.
Players are the following:
USSR (player 0)
USA (player 1)
China (player 3)
Great Britain (player 5)
Italy (player 6)
Germany (player 8)
Finland (player 10)
Japan (player 11)
Player slots not mentioned are not in use.
I seriously have no idea why this is happening, the system is confusing enough as it is with all it's loops and sorting algorithms, so can anyone help me with this?
*Every x seconds, the script groups your allies and sorts them in an array based on how many ports they have. Ally with most ports is 1, ally with second most ports is 2, etc.
*The system groups all your ports and orders the first one in the group to send a trade ship towards the closest port owned by the first ally in the list. The second port will send to the second player in the list, and so on. If there are more ports then allies, it will start over from the top.
*The map is divided into two "theatres", one asian and one european. For this reason, the system has to run once for each theatre to make sure that no ships attempt to cross the border. You will see how this works in the script.
*If a player has no allies with ports in the same theatre, he will not send any trade ships.
Here is the code:
JASS:
library TradeSys initializer Init requires GetClosestWidget
//Credits to this library goes to Spinnaker.
globals
private integer handler = 0 //this variable is used for deciding which theatre to use - ports in the asian theatre are stored in "ports[i+handler]"
private timer timers = CreateTimer()
private force traders = CreateForce()
private trigger trig = CreateTrigger()
public integer array numports
public group array ports
private player array players
private constant integer HARBOR_ID = 'h00R'
private constant integer SHIP_ID = 'h01B' //ID of the trade ship that will be spawned
private constant real INTERVAL = 20. //Interval between the shipments
endglobals
////////////////////////////////////////////////////
private function Swap takes player a, player b returns nothing
local player p = a
set a = b
set b = p
set p = null
endfunction
private function SelectSort takes integer n returns nothing //This trigger sorts the allies depending on ammount of ports.
local integer i = 0
local integer j
local integer m
loop
exitwhen i > n
set m = i
set j = i + 1
loop
exitwhen j > n
if numports[GetPlayerId(players[j])+handler] < numports[GetPlayerId(players[m])+handler] then
set m = j
endif
set j = j + 1
endloop
call Swap(players[m], players[i])
set i = i + 1
endloop
endfunction
private function Execute takes nothing returns nothing
local unit u
local unit e
local integer i = 0
local integer m = 0
local integer n = 0
local player p = GetEnumPlayer()
local player q
loop
exitwhen i > 11
set q = Player(i)
if GetPlayerAlliance(p, q, ALLIANCE_SHARED_VISION) and p != q and numports[GetPlayerId(q)+handler] > 0 then
set players[n] = Player(i)
set n = n + 1
endif
set i = i + 1
endloop
set m = n - 1
call SelectSort(m)
call GroupClear(bj_lastCreatedGroup)
call ForGroup(ports[GetPlayerId(p)+handler], function AddGroupEnum)
loop
set u = FirstOfGroup(bj_lastCreatedGroup)
exitwhen u == null
if 0 == m then
set m = n - 1
else
set m = m - 1
endif
set bj_lastCreatedUnit = CreateUnit(p, SHIP_ID, GetUnitX(u), GetUnitY(u), 0)
set e = GetClosestUnitInGroup(GetUnitX(u), GetUnitY(u), ports[m+handler])
//call IssueTargetOrder(bj_lastCreatedUnit, "channel", u)
call IssueTargetOrderById(bj_lastCreatedUnit, OrderId("thunderbolt"), e) //This is just a dummy spell to register when the ship reaches it's destination.
call GroupRemoveUnit(bj_lastCreatedGroup, u)
endloop
set e = null
set p = null
set q = null
set u = null
endfunction
private function CallBack takes nothing returns nothing
set handler = 0
call ForForce(traders, function Execute) //For european theatre
set handler = 12
call ForForce(traders, function Execute) //For asian theatre
endfunction
private function SortHarbors takes nothing returns boolean
//This decides wether a port is in the european or asian theatre.
//All units above -2500 are in the european theatre, all below -2000 are in asian.
//This trigger is used in the beginning of the game to sort the ports into the array.
local unit u = GetFilterUnit()
local integer i = GetPlayerId(GetOwningPlayer(u))
if GetUnitTypeId(u) == HARBOR_ID then
if GetUnitY(u) <= -2000 then
set numports[i] = numports[i] + 1
call GroupAddUnit(ports[i], u)
elseif GetUnitY(u) >= -2500 then
set numports[i+12] = numports[i+12] + 1
call GroupAddUnit(ports[i+12], u)
endif
endif
set u = null
return false
endfunction
private function Init takes nothing returns nothing
local integer i = 0
local player p
loop
exitwhen i > 11
set p = Player(i)
// if GetPlayerController(p) == MAP_CONTROL_USER and GetPlayerSlotState(p) == PLAYER_SLOT_STATE_PLAYING then
// I commented above statement out in order to try the system in single player
call ForceAddPlayer(traders, p)
if ports[i] == null then
set ports[i] = CreateGroup()
endif
set handler = i + 12
if ports[handler] == null then
set ports[handler] = CreateGroup()
endif
// endif
call GroupEnumUnitsOfPlayer(bj_lastCreatedGroup, p, Filter(function SortHarbors))
set i = i + 1
endloop
call TimerStart(timers, INTERVAL, true, function CallBack)
set p = null
endfunction
endlibrary
And here is a snippet from the code for capturing ports - not that it is of any interrest:
JASS:
if GetUnitTypeId(u) == 'h00R' then
if GetUnitY(u) <= -2000 then
set TradeSys_numports[b] = TradeSys_numports[b] + 1
set TradeSys_numports[a] = TradeSys_numports[a] - 1
call GroupAddUnit(TradeSys_ports[b], u)
call GroupRemoveUnit(TradeSys_ports[a], u)
else
set a = a + 12
set b = b + 12
set TradeSys_numports[b] = TradeSys_numports[b] + 1
set TradeSys_numports[a] = TradeSys_numports[a] - 1
call GroupAddUnit(TradeSys_ports[b], u)
call GroupRemoveUnit(TradeSys_ports[a], u)
endif
endif
Here is a shot of the minimap, for better understanding:
Now, my problem is, that some players will not send their ships - Japan and USA both send no ships whatsoever (they spawn, but don't move), while for other players, some individual ports won't send, like Arkhangel'sk, Singapore, etc.
Another problem is that some axis players send ships to allied players, even though they are enemies. For instance, finish port in Petsamo sends ships to russian Murmansk.
The ones that work flawlessly are:
GB Port Morseby to USSR Vladivostok - this trade route functions perfectly.
Chineese port below Changsha to USSR vladivostok - also this works as planned
USSR Vladivostok to US Pearl Harbour - this works well, but since US player won't send ships, they cluster up, and hence the USSR ships can't get past.
GB London to US New York - same as above
All german ports somehow insist on sending their ships to USSR port in Arkhangel'sk, which is unallied
Finnish ports in Petsamo and Oulu both insists on sending ships to unallied USSR port in Murmansk
Please note that this is in the beginning when n ports had been captured. I was playing as USSR.
Players are the following:
USSR (player 0)
USA (player 1)
China (player 3)
Great Britain (player 5)
Italy (player 6)
Germany (player 8)
Finland (player 10)
Japan (player 11)
Player slots not mentioned are not in use.
I seriously have no idea why this is happening, the system is confusing enough as it is with all it's loops and sorting algorithms, so can anyone help me with this?
Last edited: