controls.cpp

Go to the documentation of this file.
00001 
00007 /*
00008     This file is part of Advanced Strategic Command; http://www.asc-hq.de
00009     Copyright (C) 1994-2010  Martin Bickel  and  Marc Schellenberger
00010 
00011     This program is free software; you can redistribute it and/or modify
00012     it under the terms of the GNU General Public License as published by
00013     the Free Software Foundation; either version 2 of the License, or
00014     (at your option) any later version.
00015 
00016     This program is distributed in the hope that it will be useful,
00017     but WITHOUT ANY WARRANTY; without even the implied warranty of
00018     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019     GNU General Public License for more details.
00020 
00021     You should have received a copy of the GNU General Public License
00022     along with this program; see the file COPYING. If not, write to the 
00023     Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
00024     Boston, MA  02111-1307  USA
00025 */
00026 
00027 #include <stdio.h>           
00028 #include <cstring>
00029 #include <math.h>
00030 #include <stdarg.h>
00031 #include <ctime>
00032 
00033 #include "buildingtype.h"
00034 #include "vehicletype.h"
00035 #include "typen.h"
00036 
00037 #include "spfst.h"
00038 #include "loaders.h"
00039 #include "controls.h"
00040 #include "attack.h"
00041 #include "gameoptions.h"
00042 #include "errors.h"
00043 #include "viewcalculation.h"
00044 #include "replay.h"
00045 #include "resourcenet.h"
00046 #include "stack.h"
00047 
00048 
00049 bool checkUnitsForCrash( Player& player, ASCString& text )
00050 {
00051    bool endangeredUnits = false;
00052    
00053    for ( Player::VehicleList::const_iterator i = player.vehicleList.begin(); i != player.vehicleList.end(); ++i ) {
00054       int endurance = UnitHooveringLogic::getEndurance( *i );
00055       if ( endurance>= 0 && endurance <= CGameOptions::Instance()->aircraftCrashWarningTime ) {
00056          endangeredUnits = true;
00057          text += (*i)->getName() + " " + (*i)->getPosition().toString() + "\n";
00058       }
00059         
00060    }
00061    return endangeredUnits;
00062 }
00063 
00064 
00065 
00066 
00067 int windbeeline ( const MapCoordinate& start, const MapCoordinate& dest, WindMovement* wm ) {
00068    int x1 = start.x;
00069    int y1 = start.y;
00070    int dist = 0;
00071    while ( x1 != dest.x  || y1 != dest.y ) {
00072       dist+= minmalq;
00073       int direc = getdirection ( x1, y1, dest.x, dest.y );
00074       dist -= wm->getDist(direc);
00075       getnextfield ( x1, y1, direc );
00076    }
00077    return dist;
00078 }
00079 
00080 
00081 
00082 pair<int,int> calcMoveMalus( const MapCoordinate3D& start,
00083                             const MapCoordinate3D& dest,
00084                             const Vehicle*     vehicle,
00085                             WindMovement* wm,
00086                             bool*  inhibitAttack,
00087                             bool container2container )
00088 {
00089    int direc = getdirection ( start.x, start.y, dest.x, dest.y );
00090 
00091 
00092    int fuelcost = 10;
00093    int movecost;
00094    bool checkHemming = true;
00095    bool checkWind = wm != NULL;
00096    int dist = 1;
00097 
00098    if ( start.getNumericalHeight() >= 0 && dest.getNumericalHeight() >= 0 ) {
00099 
00100       // changing height
00101       if ( (start.getNumericalHeight() != dest.getNumericalHeight()) && !container2container ) {
00102           const VehicleType::HeightChangeMethod* hcm = vehicle->getHeightChange( start.getNumericalHeight() < dest.getNumericalHeight() ? 1 : -1, start.getBitmappedHeight());
00103           if ( !hcm || hcm->dist != beeline ( start, dest )/maxmalq )
00104              fatalError("Calcmovemalus called with invalid height change distance");
00105           dist = hcm->dist;
00106           movecost = hcm->moveCost;
00107           fuelcost = max(hcm->dist*10,10);
00108           if ( inhibitAttack && !hcm->canAttack )
00109             *inhibitAttack = !hcm->canAttack;
00110           checkHemming = false;
00111           if ( start.getNumericalHeight() < 4 || dest.getNumericalHeight() < 4 )
00112              checkWind = false;
00113       } else
00114          // flying
00115          if (start.getNumericalHeight() >= 4 )
00116             movecost = maxmalq;
00117          else
00118             if ( start.getNumericalHeight() <= 1 ) {
00119                movecost = submarineMovement;
00120                checkWind = false;
00121             } else {
00122                // not flying
00123                MapField* fld = vehicle->getMap()->getField( dest.x, dest.y );
00124                if ( fld->building )
00125                   movecost = maxmalq;
00126                else
00127                   movecost = fld->getmovemalus( vehicle );
00128                checkWind = false;
00129             }
00130 
00131    } else
00132       if ( dest.getNumericalHeight() >= 0 ) {
00133         // moving out of container
00134         int mm;
00135         const ContainerBaseType::TransportationIO* unloadSystem = vehicle->getMap()->getField( start.x, start.y )->getContainer()->vehicleUnloadSystem( vehicle->typ, dest.getBitmappedHeight() );
00136         if ( unloadSystem )
00137             mm = unloadSystem->movecost;
00138         else
00139            mm = 0;
00140         
00141         if ( mm > 0 )
00142             movecost = mm;
00143         else {
00144             if ( dest.getNumericalHeight() >= 4 )
00145                // flying
00146                movecost = maxmalq;
00147             else {
00148                if ( dest.getNumericalHeight() <= 1 ) {
00149                   movecost = submarineMovement;
00150                   checkWind = false;
00151                } else {
00152                   movecost = vehicle->getMap()->getField( dest.x, dest.y )->getmovemalus( vehicle );
00153                }
00154             }
00155         }
00156       } else {
00157         // moving from one container to another
00158         movecost = maxmalq;
00159         checkHemming = false;
00160         checkWind = false;
00161       }
00162 
00163    static const  int         movemalus[6]  = { 0, 3, 5, 0, 5, 3 };
00164    
00165    if ( checkHemming )
00166       for (int c = 0; c < sidenum; c++) {
00167          int x = dest.x;
00168          int y = dest.y;
00169          getnextfield( x,  y, c );
00170          MapField* fld = vehicle->getMap()->getField ( x, y );
00171          if ( fld ) {
00172            int d = (c - direc);
00173 
00174            if (d >= sidenum)
00175               d -= sidenum;
00176 
00177            if (d < 0)
00178               d += sidenum;
00179 
00180            MapField* fld = vehicle->getMap()->getField(x,y);
00181            if ( fld->vehicle && dest.getNumericalHeight() >= 0 ) {
00182               if ( vehicle->getMap()->getPlayer(vehicle).diplomacy.isHostile( fld->vehicle->getOwner() ) )
00183                  if ( attackpossible28(fld->vehicle,vehicle, NULL, dest.getBitmappedHeight() ))
00184                     movecost += movemalus[d];
00185               
00186            }
00187          }
00188       }
00189 
00190     /*******************************/
00191     /*    Wind calculation         */
00192     /*******************************/
00193    if ( wm && checkWind && direc >= 0 && direc < 5 )
00194       if (dest.getNumericalHeight() >= 4 && dest.getNumericalHeight() <= 6 &&
00195           start.getNumericalHeight() >= 4 && start.getNumericalHeight() <= 6 &&
00196           vehicle->getMap()->weather.windSpeed  ) {
00197          movecost -=  wm->getDist( direc ) * dist;
00198          fuelcost -=  wm->getDist ( direc ) * dist;
00199 
00200          if ( movecost < 1 )
00201            movecost = 1;
00202 
00203          if ( fuelcost <= 0 )
00204            fuelcost = 0;
00205       }
00206    return make_pair(movecost,fuelcost);
00207 }
00208 
00209 
00210 
00211 
00212 
00213 
00214 void Building :: execnetcontrol ( void )
00215 {
00216    for ( int i = 0; i < 3; i++ )
00217       if ( !getMap()->isResourceGlobal(i) ) {
00218          if (  netcontrol & (cnet_moveenergyout << i )) {
00219             npush (  netcontrol );
00220             netcontrol |= (cnet_stopenergyinput << i );
00221             actstorage.resource(i) -= putResource ( actstorage.resource(i), i, 0 );
00222             npop (  netcontrol );
00223          } else
00224             if (  netcontrol & (cnet_storeenergy << i )) {
00225                npush (  netcontrol );
00226                netcontrol |= (cnet_stopenergyoutput << i );
00227                actstorage.resource(i) += getResource ( getStorageCapacity().resource(i) -  actstorage.resource(i), i, false );
00228                npop (  netcontrol );
00229             }
00230       }
00231 
00232 }
00233 
00234                     /*   modes: 0 = energy   ohne abbuchen
00235                                 1 = material ohne abbuchen
00236                                 2 = fuel     ohne abbuchen
00237 
00238                                   +4         mit abbuchen                         /
00239                                   +8         nur Tributzahlungen kassieren       /
00240                                  +16         plus zurueckliefern                 <  diese Bits schliessen sich gegenseitig aus
00241                                  +32         usage zurueckliefern                 \
00242                                  +64         tank zurueckliefern                   \
00243                                  */
00244 
00245 
00246 int  Building :: putResource ( int      need,    int resourcetype, bool queryonly, int scope, int player  )
00247 {
00248    if ( need < 0 )
00249       return -getResource( -need, resourcetype, queryonly, scope, player );
00250    else {
00251       int placed;
00252       {
00253          PutResource putresource ( getMap(), scope );
00254          placed = putresource.getresource ( entryPosition.x, entryPosition.y, resourcetype, need, queryonly, player >= 0 ? player : getMap()->actplayer, scope );
00255       }
00256       // if ( !queryonly && placed > 0 )
00257       //   resourceChanged();
00258       return placed;
00259    }
00260 }
00261 
00262 
00263 int  Building :: getResource ( int      need,    int resourcetype, bool queryonly, int scope, int player )
00264 {
00265    if ( need < 0 )
00266       return -putResource( -need, resourcetype, queryonly, scope, player );
00267    else {
00268       int got;
00269       {
00270          GetResource gr ( getMap(), scope );
00271          got = gr.getresource ( entryPosition.x, entryPosition.y, resourcetype, need, queryonly, player >= 0 ? player : getMap()->actplayer, scope );
00272       }
00273       // if ( !queryonly && got > 0 )
00274       //   resourceChanged();
00275       return got;
00276       
00277    }
00278 }
00279 
00280 int  Building :: getAvailableResource ( int      need,    int resourcetype, int scope ) const
00281 {
00282    int got;
00283    {
00284       GetResource gr ( getMap(), scope );
00285       got = gr.getresource ( entryPosition.x, entryPosition.y, resourcetype, need, true, getMap()->actplayer, scope );
00286    }
00287    return got;
00288 }
00289 

Generated on Mon May 21 01:26:30 2012 for Advanced Strategic Command by  doxygen 1.5.1