@@ -621,9 +621,114 @@ public boolean canMake(final UnitType type) {
621621 return canMake (type , null );
622622 }
623623
624- //TODO
625624 public boolean canMake (final UnitType type , final Unit builder ) {
626- return true ;
625+ Player pSelf = self ();
626+ // Error checking
627+ if (pSelf == null ) {
628+ return false ;
629+ }
630+
631+ // Check if the unit type is available (UMS game)
632+ if ( !pSelf .isUnitAvailable (type ) ) {
633+ return false ;
634+ }
635+
636+ // Get the required UnitType
637+ final UnitType requiredType = type .whatBuilds ().getKey ();
638+
639+ // do checks if a builder is provided
640+ if ( builder != null ) {
641+ // Check if the owner of the unit is you
642+ if (!pSelf .equals (builder .getPlayer ())) {
643+ return false ;
644+ }
645+
646+ final UnitType builderType = builder .getType ();
647+ if ( type == Zerg_Nydus_Canal && builderType == Zerg_Nydus_Canal ) {
648+ if ( !builder .isCompleted () ) {
649+ return false ;
650+ }
651+ return builder .getNydusExit () == null ;
652+ }
653+
654+ // Check if this unit can actually build the unit type
655+ if ( requiredType == Zerg_Larva && builderType .producesLarva () ) {
656+ if ( builder .getLarva ().size () == 0 ) {
657+ return false ;
658+ }
659+ }
660+ else if ( builderType != requiredType ) {
661+ return false ;
662+ }
663+
664+ // Carrier/Reaver space checking
665+ int max_amt ;
666+ switch ( builderType ) {
667+ case Protoss_Carrier :
668+ case Hero_Gantrithor :
669+ // Get max interceptors
670+ max_amt = 4 ;
671+ if ( pSelf .getUpgradeLevel (UpgradeType .Carrier_Capacity ) > 0 || builderType == Hero_Gantrithor ) {
672+ max_amt += 4 ;
673+ }
674+
675+ // Check if there is room
676+ if ( builder .getInterceptorCount () + builder .getTrainingQueue ().size () >= max_amt ) {
677+ return false ;
678+ }
679+ break ;
680+ case Protoss_Reaver :
681+ case Hero_Warbringer :
682+ // Get max scarabs
683+ max_amt = 5 ;
684+ if ( pSelf .getUpgradeLevel (UpgradeType .Reaver_Capacity ) > 0 || builderType == Hero_Warbringer ) {
685+ max_amt += 5 ;
686+ }
687+
688+ // check if there is room
689+ if (builder .getScarabCount () + builder .getTrainingQueue ().size () >= max_amt ) {
690+ return false ;
691+ }
692+ break ;
693+ }
694+ } // if builder != nullptr
695+
696+ // Check if player has enough minerals
697+ if ( pSelf .minerals () < type .mineralPrice () ) {
698+ return false ;
699+ }
700+
701+ // Check if player has enough gas
702+ if ( pSelf .gas () < type .gasPrice () ) {
703+ return false ;
704+ }
705+
706+ // Check if player has enough supplies
707+ Race typeRace = type .getRace ();
708+ final int supplyRequired = type .supplyRequired () * (type .isTwoUnitsInOneEgg () ? 2 : 1 );
709+ if (supplyRequired > 0 && pSelf .supplyTotal (typeRace ) < pSelf .supplyUsed (typeRace ) + supplyRequired - (requiredType .getRace () == typeRace ? requiredType .supplyRequired () : 0 )) {
710+ return false ;
711+ }
712+
713+ UnitType addon = UnitType .None ;
714+ Map <UnitType , Integer > reqUnits = type .requiredUnits ();
715+ for (final UnitType ut : type .requiredUnits ().keySet ()) {
716+ if (ut .isAddon ())
717+ addon = ut ;
718+
719+ if (!pSelf .hasUnitTypeRequirement (ut , reqUnits .get (ut ))) {
720+ return false ;
721+ }
722+ }
723+
724+ if (type .requiredTech () != TechType .None && !pSelf .hasResearched (type .requiredTech ())) {
725+ return false ;
726+ }
727+
728+ return builder == null ||
729+ addon == UnitType .None ||
730+ addon .whatBuilds ().getKey () != type .whatBuilds ().getKey () ||
731+ (builder .getAddon () != null && builder .getAddon ().getType () == addon );
627732 }
628733
629734 public boolean canResearch (final TechType type , final Unit unit ) {
@@ -634,8 +739,50 @@ public boolean canResearch(final TechType type) {
634739 return canResearch (type , null );
635740 }
636741
637- //TODO
638742 public boolean canResearch (final TechType type , final Unit unit , final boolean checkCanIssueCommandType ) {
743+ final Player self = self ();
744+ // Error checking
745+ if ( self == null ) {
746+ return false ;
747+ }
748+
749+ if ( unit != null ) {
750+ if (!unit .getPlayer ().equals (self )) {
751+ return false ;
752+ }
753+
754+ if (!unit .getType ().isSuccessorOf (type .whatResearches ())) {
755+ return false ;
756+ }
757+
758+ if ( checkCanIssueCommandType && ( unit .isLifted () || !unit .isIdle () || !unit .isCompleted () ) ) {
759+ return false ;
760+ }
761+ }
762+ if (self .isResearching (type )) {
763+ return false ;
764+ }
765+
766+ if (self .hasResearched (type )) {
767+ return false ;
768+ }
769+
770+ if ( !self .isResearchAvailable (type ) ) {
771+ return false ;
772+ }
773+
774+ if (self .minerals () < type .mineralPrice ()) {
775+ return false ;
776+ }
777+
778+ if (self .gas () < type .gasPrice ()) {
779+ return false ;
780+ }
781+
782+ if (!self .hasUnitTypeRequirement (type .requiredUnit ())) {
783+ return false ;
784+ }
785+
639786 return true ;
640787 }
641788
@@ -647,13 +794,51 @@ public boolean canUpgrade(final UpgradeType type) {
647794 return canUpgrade (type , null );
648795 }
649796
650- //TODO
651797 public boolean canUpgrade (final UpgradeType type , final Unit unit , final boolean checkCanIssueCommandType ) {
652- return true ;
798+ final Player self = self ();
799+ if ( self == null ) {
800+ return false ;
801+ }
802+
803+ if ( unit != null ) {
804+ if (!unit .getPlayer ().equals (self )) {
805+ return false ;
806+ }
807+
808+ if (!unit .getType ().isSuccessorOf (type .whatUpgrades ())) {
809+ return false ;
810+ }
811+
812+ if ( checkCanIssueCommandType && ( unit .isLifted () || !unit .isIdle () || !unit .isCompleted ())) {
813+ return false ;
814+ }
815+ }
816+ int nextLvl = self .getUpgradeLevel (type ) + 1 ;
817+
818+ if (!self .hasUnitTypeRequirement (type .whatUpgrades ())) {
819+ return false ;
820+ }
821+
822+ if (!self .hasUnitTypeRequirement (type .whatsRequired (nextLvl ))) {
823+ return false ;
824+ }
825+
826+ if (self .isUpgrading (type )) {
827+ return false ;
828+ }
829+
830+ if ( self .getUpgradeLevel (type ) >= self .getMaxUpgradeLevel (type )) {
831+ return false ;
832+ }
833+
834+ if ( self .minerals () < type .mineralPrice (nextLvl )) {
835+ return false ;
836+ }
837+
838+ return self .gas () >= type .gasPrice (nextLvl );
653839 }
654840
655841 public List <TilePosition > getStartLocations () {
656- //TODO cache this?
657842 return IntStream .range (0 , gameData .startLocationCount ())
658843 .mapToObj (i -> new TilePosition (gameData .startLocationX (i ), gameData .startLocationY (i )))
659844 .collect (Collectors .toList ());
0 commit comments