1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-20 20:23:03 +02:00

* CGameInterface.h/.cpp moved from client project to lib (and, appropriately, to lib subfolder).

* New files in lib: ResourceSet.h/.cpp -> containing new structure for managing resources logic
* Minor changes and fixes
This commit is contained in:
Michał W. Urbańczyk 2011-07-05 06:14:07 +00:00
parent 08b7d0db17
commit b3234e8bfa
28 changed files with 490 additions and 191 deletions

View File

@ -325,8 +325,8 @@ float CGeniusAI::TownObjective::getValue() const
newID = ui.newID.back();
int upgrade_serial = ui.newID.size() - 1;
for (std::set< std::pair<int,int> >::iterator j = ui.cost[upgrade_serial].begin(); j != ui.cost[upgrade_serial].end(); j++)
resourceCosts[j->first] = j->second*howMany;
// for (std::set< std::pair<int,int> >::iterator j = ui.cost[upgrade_serial].begin(); j != ui.cost[upgrade_serial].end(); j++)
// resourceCosts[j->first] = j->second*howMany;
break;
}
@ -762,9 +762,9 @@ void CGeniusAI::HeroObjective::fulfill(CGeniusAI& cg, HypotheticalGameState& hgs
std::set<std::pair<int,int> >::iterator j;
for (int ii = 0; ii < ui.cost.size(); ii++) // Can afford the upgrade?
{
for (j = ui.cost[ii].begin(); j != ui.cost[ii].end(); j++)
if (hgs.resourceAmounts[j->first] < j->second * i->second->count)
canUpgrade = false;
// for (j = ui.cost[ii].begin(); j != ui.cost[ii].end(); j++)
// if (hgs.resourceAmounts[j->first] < j->second * i->second->count)
// canUpgrade = false;
}
}
if (canUpgrade)
@ -889,11 +889,11 @@ void CGeniusAI::addTownObjectives (HypotheticalGameState::TownModel& t, Hypothet
bool canAfford = true;
int upgrade_serial = ui.newID.size() - 1;
for (std::set< std::pair<int, int> >::iterator j = ui.cost[upgrade_serial].begin(); j != ui.cost[upgrade_serial].end(); j++)
{
if (hgs.resourceAmounts[j->first] < j->second * i->second->count)
canAfford = false;
}
// for (std::set< std::pair<int, int> >::iterator j = ui.cost[upgrade_serial].begin(); j != ui.cost[upgrade_serial].end(); j++)
// {
// if (hgs.resourceAmounts[j->first] < j->second * i->second->count)
// canAfford = false;
// }
if (canAfford)
{
TownObjective to(hgs,AIObjective::upgradeCreatures,&t,i->first,this);

View File

@ -3,7 +3,7 @@
#include <vector>
#include <iostream>
#include "CGameInterface.h"
#include "lib/CGameInterface.h"
/*
* AI_Base.h, part of VCMI engine

View File

@ -157,14 +157,17 @@ bool CCallback::assembleArtifacts (const CGHeroInstance * hero, ui16 artifactSlo
bool CCallback::buildBuilding(const CGTownInstance *town, si32 buildingID)
{
CGTownInstance * t = const_cast<CGTownInstance *>(town);
//CGTownInstance * t = const_cast<CGTownInstance *>(town);
if(town->tempOwner!=player)
return false;
const CBuilding *b = CGI->buildh->buildings[t->subID][buildingID];
for(int i=0;i<b->resources.size();i++)
if(b->resources[i] > gs->players[player].resources[i])
return false; //lack of resources
if(!canBuildStructure(town, buildingID))
return false;
// const CBuilding *b = CGI->buildh->buildings[t->subID][buildingID];
// for(int i=0;i<b->resources.size();i++)
// if(b->resources[i] > gs->players[player].resources[i])
// return false; //lack of resources
BuildStructure pack(town->id,buildingID);
sendRequest(&pack);

View File

@ -82,16 +82,14 @@ CCreatureWindow::CCreatureWindow(const CStackInstance &st, int Type, boost::func
{
if(Upg && ui)
{
bool enough = true;
for(std::set<std::pair<int,int> >::iterator i=ui->cost[0].begin(); i!=ui->cost[0].end(); i++) //calculate upgrade cost
TResources upgradeCost = ui->cost[0] * st.count;
for(TResources::nziterator i(upgradeCost); i.valid(); i++)
{
BLOCK_CAPTURING;
if(LOCPLINT->cb->getResourceAmount(i->first) < i->second*st.count)
enough = false;
upgResCost.push_back(new SComponent(SComponent::resource,i->first,i->second*st.count));
upgResCost.push_back(new SComponent(SComponent::resource, i->resType, i->resVal));
}
if(enough)
if(LOCPLINT->cb->getResourceAmount().canAfford(upgradeCost))
{
CFunctionList<void()> fs;
fs += Upg;

View File

@ -1,12 +1,13 @@
#ifndef __CPLAYERINTERFACE_H__
#define __CPLAYERINTERFACE_H__
#include "../global.h"
#include "../CGameInterface.h"
#include "../lib/CGameInterface.h"
#include "../lib/CondSh.h"
#include <map>
#include <list>
#include <algorithm>
#include "GUIBase.h"
#include "FunctionList.h"
#ifdef __GNUC__
#define sprintf_s snprintf

View File

@ -820,6 +820,11 @@ void CIntObject::changeUsedEvents(ui16 what, bool enable, bool adjust /*= true*/
}
}
void CIntObject::drawBorderLoc(SDL_Surface * sur, const Rect &r, const int3 &color)
{
CSDL_Ext::drawBorder(sur, r + pos, color);
}
CPicture::CPicture( SDL_Surface *BG, int x, int y, bool Free )
{
init();

View File

@ -416,6 +416,7 @@ public:
void show(SDL_Surface * to);
void showAll(SDL_Surface * to);
void drawBorderLoc(SDL_Surface * sur, const Rect &r, const int3 &color);
void printAtLoc(const std::string & text, int x, int y, EFonts font, SDL_Color kolor, SDL_Surface * dst);
void printToLoc(const std::string & text, int x, int y, EFonts font, SDL_Color kolor, SDL_Surface * dst);
void printAtMiddleLoc(const std::string & text, int x, int y, EFonts font, SDL_Color kolor, SDL_Surface * dst);

View File

@ -1741,7 +1741,7 @@ void CRecruitmentWindow::clickLeft(tribool down, bool previousState)
{
for(int i=0;i<creatures.size();i++)
{
Rect creaPos = pos + creatures[i].pos;
Rect creaPos = Rect(creatures[i].pos) + pos;
if(isItIn(&creaPos, GH.current->motion.x, GH.current->motion.y))
{
which = i;
@ -1804,9 +1804,9 @@ void CRecruitmentWindow::showAll( SDL_Surface * to )
for(int j=0;j<creatures.size();j++)
{
if(which==j)
drawBorder(*bitmap,creatures[j].pos,int3(255,0,0));
drawBorderLoc(to,creatures[j].pos,int3(255,0,0));
else
drawBorder(*bitmap,creatures[j].pos,int3(239,215,123));
drawBorderLoc(to,creatures[j].pos,int3(239,215,123));
}
}
@ -2076,22 +2076,20 @@ CCreInfoWindow::CCreInfoWindow(const CStackInstance &st, int Type, boost::functi
{
if(Upg && ui)
{
bool enough = true;
for(std::set<std::pair<int,int> >::iterator i=ui->cost[0].begin(); i!=ui->cost[0].end(); i++) //calculate upgrade cost
TResources upgradeCost = ui->cost[0] * st.count;
for(TResources::nziterator i(upgradeCost); i.valid(); i++)
{
BLOCK_CAPTURING;
if(LOCPLINT->cb->getResourceAmount(i->first) < i->second*st.count)
enough = false;
upgResCost.push_back(new SComponent(SComponent::resource,i->first,i->second*st.count));
upgResCost.push_back(new SComponent(SComponent::resource, i->resType, i->resVal));
}
if(enough)
if(LOCPLINT->cb->getResourceAmount().canAfford(upgradeCost))
{
CFunctionList<void()> fs;
fs += Upg;
fs += boost::bind(&CCreInfoWindow::close,this);
CFunctionList<void()> cfl;
cfl = boost::bind(&CPlayerInterface::showYesNoDialog, LOCPLINT, CGI->generaltexth->allTexts[207], boost::ref(upgResCost), fs, 0, false);
cfl = boost::bind(&CPlayerInterface::showYesNoDialog, LOCPLINT, CGI->generaltexth->allTexts[207], boost::ref(upgResCost), fs, 0, true);
upgrade = new AdventureMapButton("",CGI->generaltexth->zelp[446].second,cfl,76,237,"IVIEWCR.DEF",SDLK_u);
}
else
@ -2109,7 +2107,7 @@ CCreInfoWindow::CCreInfoWindow(const CStackInstance &st, int Type, boost::functi
fs[0] += Dsm; //dismiss
fs[0] += boost::bind(&CCreInfoWindow::close,this);//close this window
CFunctionList<void()> cfl;
cfl = boost::bind(&CPlayerInterface::showYesNoDialog,LOCPLINT,CGI->generaltexth->allTexts[12],std::vector<SComponent*>(),fs[0],fs[1],false);
cfl = boost::bind(&CPlayerInterface::showYesNoDialog,LOCPLINT,CGI->generaltexth->allTexts[12],std::vector<SComponent*>(),fs[0],fs[1],true);
dismiss = new AdventureMapButton("",CGI->generaltexth->zelp[445].second,cfl,21,237,"IVIEWCR2.DEF",SDLK_d);
}
ok = new AdventureMapButton("",CGI->generaltexth->zelp[445].second,boost::bind(&CCreInfoWindow::close,this),216,237,"IOKAY.DEF",SDLK_RETURN);
@ -6417,12 +6415,10 @@ void CHillFortWindow::updateGarrisons()
UpgradeInfo info;
LOCPLINT->cb->getUpgradeInfo(hero, i, info);
if (info.newID.size())//we have upgrades here - update costs
for(std::set<std::pair<int,int> >::iterator it=info.cost[0].begin(); it!=info.cost[0].end(); it++)
{
std::pair<int, int> pair = std::make_pair(it->first, it->second * hero->getStackCount(i) );
costs[i].insert(pair);
totalSumm[pair.first] += pair.second;
}
{
costs[i] = info.cost[0] * hero->getStackCount(i);
totalSumm += costs[i];
}
}
currState[i] = newState;
@ -6474,10 +6470,13 @@ void CHillFortWindow::showAll (SDL_Surface *to)
if ( costs[i].size() )//we have several elements
{
int curY = 128;//reverse iterator is used to display gold as first element
for( std::map<int,int>::reverse_iterator rit=costs[i].rbegin(); rit!=costs[i].rend(); rit++)
for(int j = costs[i].size()-1; j >= 0; j--)
{
blitAtLoc(resources->ourImages[rit->first].bitmap, 104+76*i, curY, to);
printToLoc(boost::lexical_cast<std::string>(rit->second), 168+76*i, curY+16, FONT_SMALL, zwykly, to);
int val = costs[i][j];
if(!val) continue;
blitAtLoc(resources->ourImages[j].bitmap, 104+76*i, curY, to);
printToLoc(boost::lexical_cast<std::string>(val), 168+76*i, curY+16, FONT_SMALL, zwykly, to);
curY += 20;
}
}
@ -6515,6 +6514,7 @@ std::string CHillFortWindow::getTextForSlot(int slot)
int CHillFortWindow::getState(int slot)
{
TResources myRes = LOCPLINT->cb->getResourceAmount();
if ( slot == slotsCount )//"Upgrade all" slot
{
bool allUpgraded = true;//All creatures are upgraded?
@ -6524,10 +6524,9 @@ int CHillFortWindow::getState(int slot)
if (allUpgraded)
return 1;
for ( int i=0; i<RESOURCE_QUANTITY; i++)//if we need more resources
if(LOCPLINT->cb->getResourceAmount(i) < totalSumm[i])
return 0;
if(!totalSumm.canBeAfforded(myRes))
return 0;
return 2;
}
@ -6539,9 +6538,9 @@ int CHillFortWindow::getState(int slot)
if (!info.newID.size())//already upgraded
return 1;
for(std::set<std::pair<int,int> >::iterator it=info.cost[0].begin(); it!=info.cost[0].end(); it++)
if(LOCPLINT->cb->getResourceAmount(it->first) < it->second * hero->getStackCount(slot))
if(!(info.cost[0] * hero->getStackCount(slot)).canBeAfforded(myRes))
return 0;
return 2;//can upgrade
}

View File

@ -7,6 +7,7 @@
#include <set>
#include <list>
#include <boost/thread/mutex.hpp>
#include "../lib/ResourceSet.h"
#ifdef max
#undef max
@ -1246,8 +1247,8 @@ public:
const CGObjectInstance * fort;
const CGHeroInstance * hero;
std::vector<int> currState;//current state of slot - to avoid calls to getState or updating buttons
std::vector<std::map<int,int> > costs;// costs [slot ID] [resource ID] = resource count for upgrade
std::vector<int> totalSumm; // totalSum[resource ID] = value
std::vector<TResources> costs;// costs [slot ID] [resource ID] = resource count for upgrade
TResources totalSumm; // totalSum[resource ID] = value
CHillFortWindow(const CGHeroInstance *visitor, const CGObjectInstance *object); //c-tor
~CHillFortWindow(); //d-tor

View File

@ -183,7 +183,6 @@
<ClCompile Include="CCursorHandler.cpp" />
<ClCompile Include="CDefHandler.cpp" />
<ClCompile Include="CGameInfo.cpp" />
<ClCompile Include="..\CGameInterface.cpp" />
<ClCompile Include="CHeroWindow.cpp" />
<ClCompile Include="CKingdomInterface.cpp" />
<ClCompile Include="Client.cpp" />
@ -218,7 +217,6 @@
<ClInclude Include="CCursorHandler.h" />
<ClInclude Include="CDefHandler.h" />
<ClInclude Include="CGameInfo.h" />
<ClInclude Include="..\CGameInterface.h" />
<ClInclude Include="CHeroWindow.h" />
<ClInclude Include="CKingdomInterface.h" />
<ClInclude Include="Client.h" />

View File

@ -349,14 +349,6 @@ namespace Buildings
};
}
namespace Res
{
enum ERes
{
WOOD = 0, MERCURY, ORE, SULFUR, CRYSTAL, GEMS, GOLD, MITHRIL
};
}
namespace Arts
{
enum EPos

View File

@ -38,7 +38,6 @@ static unsigned int readNr(std::string &in, int &it)
static CBuilding * readBg(std::string &buf, int& it)
{
CBuilding * nb = new CBuilding();
nb->resources.resize(RESOURCE_QUANTITY);
for(int res=0;res<7;res++)
nb->resources[res] = readNr(buf,it);
/*nb->refName = */readTo(buf,it,'\n');

View File

@ -6,6 +6,7 @@
#include <set>
#include "../lib/ConstTransitivePtr.h"
#include "ResourceSet.h"
/*
* CBuildingHandler.h, part of VCMI engine
@ -22,7 +23,7 @@ class DLL_EXPORT CBuilding //a typical building encountered in every castle ;]
{
public:
si32 tid, bid; //town ID and structure ID
std::vector<si32> resources;
TResources resources;
std::string name;
std::string description;

View File

@ -8,6 +8,7 @@
#include "../lib/HeroBonus.h"
#include "../lib/ConstTransitivePtr.h"
#include "ResourceSet.h"
/*
* CCreatureHandler.h, part of VCMI engine
@ -28,7 +29,7 @@ class DLL_EXPORT CCreature : public CBonusSystemNode
{
public:
std::string namePl, nameSing, nameRef; //name in singular and plural form; and reference name
std::vector<ui32> cost; //cost[res_id] - amount of that resource
TResources cost; //cost[res_id] - amount of that resource
std::set<ui32> upgrades; // IDs of creatures to which this creature can be upgraded
ui32 hitPoints, speed, attack, defence;
ui32 fightValue, AIValue, growth, hordeGrowth, shots, spells;

View File

@ -1,6 +1,6 @@
#include "stdafx.h"
#define VCMI_DLL
#include "CGameInterface.h"
#include "lib/BattleState.h"
#include "BattleState.h"
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN //excludes rarely used stuff from windows headers - delete this line if something is missing
@ -102,3 +102,91 @@ BattleAction CGlobalAI::activeStack( const CStack * stack )
ba.stackNumber = stack->ID;
return ba;
}
CGlobalAI::CGlobalAI()
{
human = false;
}
void CAdventureAI::battleNewRound(int round)
{
battleAI->battleNewRound(round);
}
void CAdventureAI::battleCatapultAttacked(const CatapultAttack & ca)
{
battleAI->battleCatapultAttacked(ca);
}
void CAdventureAI::battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side)
{
assert(!battleAI);
battleAI = CDynLibHandler::getNewBattleAI(battleAIName);
battleAI->battleStart(army1, army2, tile, hero1, hero2, side);
}
void CAdventureAI::battleStacksAttacked(const std::vector<BattleStackAttacked> & bsa)
{
battleAI->battleStacksAttacked(bsa);
}
void CAdventureAI::actionStarted(const BattleAction *action)
{
battleAI->actionStarted(action);
}
void CAdventureAI::battleNewRoundFirst(int round)
{
battleAI->battleNewRoundFirst(round);
}
void CAdventureAI::actionFinished(const BattleAction *action)
{
battleAI->actionFinished(action);
}
void CAdventureAI::battleStacksEffectsSet(const SetStackEffect & sse)
{
battleAI->battleStacksEffectsSet(sse);
}
void CAdventureAI::battleStacksRemoved(const BattleStacksRemoved & bsr)
{
battleAI->battleStacksRemoved(bsr);
}
void CAdventureAI::battleObstaclesRemoved(const std::set<si32> & removedObstacles)
{
battleAI->battleObstaclesRemoved(removedObstacles);
}
void CAdventureAI::battleNewStackAppeared(const CStack * stack)
{
battleAI->battleNewStackAppeared(stack);
}
void CAdventureAI::battleStackMoved(const CStack * stack, THex dest, int distance, bool end)
{
battleAI->battleStackMoved(stack, dest, distance, end);
}
void CAdventureAI::battleAttack(const BattleAttack *ba)
{
battleAI->battleAttack(ba);
}
void CAdventureAI::battleSpellCast(const BattleSpellCast *sc)
{
battleAI->battleSpellCast(sc);
}
void CAdventureAI::battleEnd(const BattleResult *br)
{
battleAI->battleEnd(br);
delNull(battleAI);
}
void CAdventureAI::battleStacksHealedRes(const std::vector<std::pair<ui32, ui32> > & healedStacks, bool lifeDrain, bool tentHeal, si32 lifeDrainFrom)
{
battleAI->battleStacksHealedRes(healedStacks, lifeDrain, tentHeal, lifeDrainFrom);
}

View File

@ -1,11 +1,10 @@
#ifndef __CGAMEINTERFACE_H__
#define __CGAMEINTERFACE_H__
#include "global.h"
#include "../global.h"
#include <set>
#include <vector>
#include "lib/BattleAction.h"
#include "client/FunctionList.h"
#include "lib/IGameEventsReceiver.h"
#include "BattleAction.h"
#include "IGameEventsReceiver.h"
/*
* CGameInterface.h, part of VCMI engine
@ -83,7 +82,7 @@ public:
virtual void serialize(CISer<CLoadFile> &h, const int version){}; //loading
};
class CDynLibHandler
class DLL_EXPORT CDynLibHandler
{
public:
static CGlobalAI * getNewAI(std::string dllname);
@ -91,10 +90,10 @@ public:
static CScriptingModule * getNewScriptingModule(std::string dllname);
};
class CGlobalAI : public CGameInterface // AI class (to derivate)
class DLL_EXPORT CGlobalAI : public CGameInterface // AI class (to derivate)
{
public:
//CGlobalAI();
CGlobalAI();
virtual void yourTurn() OVERRIDE{};
virtual void heroKilled(const CGHeroInstance*){};
virtual void heroCreated(const CGHeroInstance*) OVERRIDE{};
@ -104,4 +103,34 @@ public:
virtual BattleAction activeStack(const CStack * stack) OVERRIDE;
};
//class to be inherited by adventure-only AIs, it cedes battle actions to given battle-AI
class DLL_EXPORT CAdventureAI : public CGlobalAI
{
public:
CAdventureAI() : battleAI(NULL) {};
CAdventureAI(const std::string &BattleAIName) : battleAIName(BattleAIName), battleAI(NULL) {};
std::string battleAIName;
CBattleGameInterface *battleAI;
//battle interface
virtual void battleNewRound(int round);
virtual void battleCatapultAttacked(const CatapultAttack & ca);
virtual void battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side);
virtual void battleStacksAttacked(const std::vector<BattleStackAttacked> & bsa);
virtual void actionStarted(const BattleAction *action);
virtual void battleNewRoundFirst(int round);
virtual void actionFinished(const BattleAction *action);
virtual void battleStacksEffectsSet(const SetStackEffect & sse);
virtual void battleStacksRemoved(const BattleStacksRemoved & bsr);
virtual void battleObstaclesRemoved(const std::set<si32> & removedObstacles);
virtual void battleNewStackAppeared(const CStack * stack);
virtual void battleStackMoved(const CStack * stack, THex dest, int distance, bool end);
virtual void battleAttack(const BattleAttack *ba);
virtual void battleSpellCast(const BattleSpellCast *sc);
virtual void battleEnd(const BattleResult *br);
virtual void battleStacksHealedRes(const std::vector<std::pair<ui32, ui32> > & healedStacks, bool lifeDrain, bool tentHeal, si32 lifeDrainFrom);
};
#endif // __CGAMEINTERFACE_H__

View File

@ -1184,7 +1184,7 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
}
/******************RESOURCES****************************************************/
std::vector<int> startresAI, startresHuman;
TResources startresAI, startresHuman;
std::ifstream tis(DATA_DIR "/config/startres.txt");
int k;
for (int j=0; j<scenarioOps->difficulty * 2; j++)
@ -1195,32 +1195,22 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
}
tis >> k;
for (int i=0; i<RESOURCE_QUANTITY; i++)
{
tis >> k;
startresHuman.push_back(k);
}
tis >> startresHuman[i];
tis >> k;
for (int i=0; i<RESOURCE_QUANTITY; i++)
{
tis >> k;
startresAI.push_back(k);
}
tis >> startresAI[i];
tis.close();
tis.clear();
for (std::map<ui8,PlayerState>::iterator i = players.begin(); i!=players.end(); i++)
{
(*i).second.resources.resize(RESOURCE_QUANTITY);
for (int x=0;x<RESOURCE_QUANTITY;x++)
{
if (i->second.human)
{
(*i).second.resources[x] = startresHuman[x];
}
else
{
(*i).second.resources[x] = startresAI[x];
}
}
PlayerState &p = i->second;
if (p.human)
p.resources = startresHuman;
else
p.resources = startresAI;
}
//give start resource bonus in case of campaign
@ -1231,7 +1221,7 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
if(chosenBonus.type == 7) //resource
{
std::vector<const PlayerSettings *> people = HLP::getHumanPlayerInfo(scenarioOps); //players we will give resource bonus
for (int b=0; b<people.size(); ++b)
BOOST_FOREACH(const PlayerSettings *ps, people)
{
std::vector<int> res; //resources we will give
switch (chosenBonus.info1)
@ -1240,10 +1230,10 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
res.push_back(chosenBonus.info1);
break;
case 0xFD: //wood+ore
res.push_back(0); res.push_back(2);
res.push_back(Res::WOOD); res.push_back(Res::ORE);
break;
case 0xFE: //rare
res.push_back(1); res.push_back(3); res.push_back(4); res.push_back(5);
res.push_back(Res::MERCURY); res.push_back(Res::SULFUR); res.push_back(Res::CRYSTAL); res.push_back(Res::GEMS);
break;
default:
assert(0);
@ -1252,7 +1242,7 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
//increasing resource quantity
for (int n=0; n<res.size(); ++n)
{
players[people[b]->color].resources[res[n]] += chosenBonus.info2;
players[ps->color].resources[res[n]] += chosenBonus.info2;
}
}
}
@ -1393,15 +1383,15 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
switch(scenarioOps->playerInfos[k->first].bonus)
{
case PlayerSettings::bgold:
k->second.resources[6] += 500 + (ran()%6)*100;
k->second.resources[Res::GOLD] += 500 + (ran()%6)*100;
break;
case PlayerSettings::bresource:
{
int res = VLC->townh->towns[scenarioOps->playerInfos[k->first].castle].primaryRes;
if(res == 127)
{
k->second.resources[0] += 5 + ran()%6;
k->second.resources[2] += 5 + ran()%6;
k->second.resources[Res::WOOD] += 5 + ran()%6;
k->second.resources[Res::ORE] += 5 + ran()%6;
}
else
{
@ -1682,10 +1672,10 @@ UpgradeInfo CGameState::getUpgradeInfo(const CStackInstance &stack)
BOOST_FOREACH(const Bonus *it, *lista)
{
ui16 nid = it->additionalInfo;
if (nid != base->idNumber) //in very specific case the upgrade is avaliable by default (?)
if (nid != base->idNumber) //in very specific case the upgrade is available by default (?)
{
ret.newID.push_back(nid);
ret.cost.push_back(costDiff(VLC->creh->creatures[nid]->cost, base->cost));
ret.cost.push_back(VLC->creh->creatures[nid]->cost - base->cost);
}
}
t = h->visitedTown;
@ -1700,7 +1690,7 @@ UpgradeInfo CGameState::getUpgradeInfo(const CStackInstance &stack)
if(vstd::contains(base->upgrades, nid)) //possible upgrade
{
ret.newID.push_back(nid);
ret.cost.push_back(costDiff(VLC->creh->creatures[nid]->cost, base->cost));
ret.cost.push_back(VLC->creh->creatures[nid]->cost - base->cost);
}
}
}
@ -1715,7 +1705,7 @@ UpgradeInfo CGameState::getUpgradeInfo(const CStackInstance &stack)
BOOST_FOREACH(si32 nid, base->upgrades)
{
ret.newID.push_back(nid);
ret.cost.push_back(costDiff(VLC->creh->creatures[nid]->cost, base->cost, costModifier));
ret.cost.push_back((VLC->creh->creatures[nid]->cost - base->cost) * costModifier / 100);
}
}
@ -2619,15 +2609,15 @@ void CGameState::obtainPlayersStats(SThievesGuildInfo & tgi, int level)
}
if(level >= 2) //gold
{
FILL_FIELD(gold, g->second.resources[6])
FILL_FIELD(gold, g->second.resources[Res::GOLD])
}
if(level >= 2) //wood & ore
{
FILL_FIELD(woodOre, g->second.resources[0] + g->second.resources[1])
FILL_FIELD(woodOre, g->second.resources[Res::WOOD] + g->second.resources[Res::ORE])
}
if(level >= 3) //mercury, sulfur, crystal, gems
{
FILL_FIELD(mercSulfCrystGems, g->second.resources[2] + g->second.resources[3] + g->second.resources[4] + g->second.resources[5])
FILL_FIELD(mercSulfCrystGems, g->second.resources[Res::MERCURY] + g->second.resources[Res::SULFUR] + g->second.resources[Res::CRYSTAL] + g->second.resources[Res::GEMS])
}
if(level >= 4) //obelisks found
{

View File

@ -23,6 +23,7 @@
#include "ConstTransitivePtr.h"
#include "IGameCallback.h"
#include "ResourceSet.h"
/*
@ -161,7 +162,7 @@ public:
ui8 human; //true if human controlled player, false for AI
ui32 currentSelection; //id of hero/town, 0xffffffff if none
ui8 team;
std::vector<si32> resources;
TResources resources;
std::vector<ConstTransitivePtr<CGHeroInstance> > heroes;
std::vector<ConstTransitivePtr<CGTownInstance> > towns;
std::vector<ConstTransitivePtr<CGHeroInstance> > availableHeroes; //heroes available in taverns
@ -209,7 +210,7 @@ struct UpgradeInfo
{
int oldID; //creature to be upgraded
std::vector<int> newID; //possible upgrades
std::vector<std::set<std::pair<int,int> > > cost; // cost[upgrade_serial] -> set of pairs<resource_ID,resource_amount>
std::vector<TResources> cost; // cost[upgrade_serial] -> set of pairs<resource_ID,resource_amount>; cost is for single unit (not entire stack)
UpgradeInfo(){oldID = -1;};
};

View File

@ -848,11 +848,8 @@ int CGameInfoCallback::canBuildStructure( const CGTownInstance *t, int ID )
return Buildings::ERROR;
//checking resources
for(int res=0; res<RESOURCE_QUANTITY; res++)
{
if(pom->resources[res] > getResource(t->tempOwner, res))
ret = Buildings::NO_RESOURCES; //lack of res
}
if(pom->resources.canBeAfforded(getPlayer(t->tempOwner)->resources))
ret = Buildings::NO_RESOURCES; //lack of res
//checking for requirements
std::set<int> reqs = getBuildingRequiments(t, ID);//getting all requirements
@ -1122,10 +1119,10 @@ int CPlayerSpecificInfoCallback::getResourceAmount(int type) const
return getResource(player, type);
}
std::vector<si32> CPlayerSpecificInfoCallback::getResourceAmount() const
TResources CPlayerSpecificInfoCallback::getResourceAmount() const
{
//boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
ERROR_RET_VAL_IF(player == -1, "Applicable only for player callbacks", std::vector<si32>());
ERROR_RET_VAL_IF(player == -1, "Applicable only for player callbacks", TResources());
return gs->players[player].resources;
}
@ -1214,7 +1211,7 @@ const CGObjectInstance * IGameCallback::putNewObject(int ID, int subID, int3 pos
no.subID= subID;
no.pos = pos;
commitPackage(&no);
return getObj(no.id); //id field will be filled during applaying on gs
return getObj(no.id); //id field will be filled during applying on gs
}
const CGCreature * IGameCallback::putNewMonster(int creID, int count, int3 pos)

View File

@ -6,6 +6,7 @@
#include <set>
#include "../client/FunctionList.h"
#include "CObstacleInstance.h"
#include "ResourceSet.h"
/*
* IGameCallback.h, part of VCMI engine
@ -213,7 +214,7 @@ public:
std::vector <const CGObjectInstance * > getMyObjects() const; //returns all objects flagged by belonging player
int getResourceAmount(int type)const;
std::vector<si32> getResourceAmount() const;
TResources getResourceAmount() const;
const std::vector< std::vector< std::vector<unsigned char> > > & getVisibilityMap()const; //returns visibility map
const PlayerSettings * getPlayerSettings(int color) const;
};

View File

@ -10,6 +10,7 @@
#include "../StartInfo.h"
#include "ConstTransitivePtr.h"
#include "../int3.h"
#include "ResourceSet.h"
/*
* NetPacks.h, part of VCMI engine
@ -238,12 +239,12 @@ struct SetResource : public CPackForClient //102
};
struct SetResources : public CPackForClient //104
{
SetResources(){res.resize(RESOURCE_QUANTITY);type = 104;};
SetResources(){type = 104;};
void applyCl(CClient *cl);
DLL_EXPORT void applyGs(CGameState *gs);
ui8 player;
std::vector<si32> res; //res[resid] => res amount
TResources res; //res[resid] => res amount
template <typename Handler> void serialize(Handler &h, const int version)
{
@ -965,7 +966,7 @@ struct NewTurn : public CPackForClient //101
std::set<Hero> heroes; //updates movement and mana points
//std::vector<SetResources> res;//resource list
std::map<ui8, std::vector<si32> > res; //player ID => resource value[res_id]
std::map<ui8, TResources> res; //player ID => resource value[res_id]
std::vector<SetAvailableCreatures> cres;//creatures to be placed in towns
ui32 day;
bool resetBuilded;

View File

@ -45,12 +45,11 @@ DLL_EXPORT void SetResource::applyGs( CGameState *gs )
gs->getPlayer(player)->resources[resid] = val;
}
DLL_EXPORT void SetResources::applyGs( CGameState *gs )
{
assert(player < PLAYER_LIMIT);
for(int i=0;i<res.size();i++)
gs->getPlayer(player)->resources[i] = res[i];
}
DLL_EXPORT void SetResources::applyGs( CGameState *gs )
{
assert(player < PLAYER_LIMIT);
gs->getPlayer(player)->resources = res;
}
DLL_EXPORT void SetPrimSkill::applyGs( CGameState *gs )
{
@ -751,12 +750,10 @@ DLL_EXPORT void NewTurn::applyGs( CGameState *gs )
hero->mana = h.mana;
}
for(std::map<ui8, std::vector<si32> >::iterator i = res.begin(); i != res.end(); i++)
for(std::map<ui8, TResources>::iterator i = res.begin(); i != res.end(); i++)
{
assert(i->first < PLAYER_LIMIT);
std::vector<si32> &playerRes = gs->getPlayer(i->first)->resources;
for(int j = 0; j < i->second.size(); j++)
playerRes[j] = i->second[j];
gs->getPlayer(i->first)->resources = i->second;
}
BOOST_FOREACH(SetAvailableCreatures h, cres) //set available creatures in towns

91
lib/ResourceSet.cpp Normal file
View File

@ -0,0 +1,91 @@
#define VCMI_DLL
#include "ResourceSet.h"
Res::ResourceSet::ResourceSet()
{
resize(RESOURCE_QUANTITY, 0);
}
bool Res::ResourceSet::nonZero() const
{
for(int i = 0; i < size(); i++)
if(at(i))
return true;
return false;
}
void Res::ResourceSet::amax(const TResource &val)
{
for(int i = 0; i < size(); i++)
::amax(at(i), val);
}
bool Res::ResourceSet::canBeAfforded(const ResourceSet &res) const
{
return Res::canAfford(res, *this);
}
bool Res::ResourceSet::canAfford(const ResourceSet &price) const
{
return Res::canAfford(*this, price);
}
bool Res::canAfford(const ResourceSet &res, const ResourceSet &price)
{
assert(res.size() == price.size() && price.size() == RESOURCE_QUANTITY);
for(int i = 0; i < RESOURCE_QUANTITY; i++)
if(price[i] > res[i])
return false;
return true;
}
bool Res::ResourceSet::nziterator::valid()
{
return cur.resType < RESOURCE_QUANTITY && cur.resVal;
}
Res::ResourceSet::nziterator Res::ResourceSet::nziterator::operator++()
{
advance();
return *this;
}
Res::ResourceSet::nziterator Res::ResourceSet::nziterator::operator++(int)
{
nziterator ret = *this;
advance();
return ret;
}
const Res::ResourceSet::nziterator::ResEntry& Res::ResourceSet::nziterator::operator*() const
{
return cur;
}
const Res::ResourceSet::nziterator::ResEntry * Res::ResourceSet::nziterator::operator->() const
{
return &cur;
}
void Res::ResourceSet::nziterator::advance()
{
do
{
cur.resType++;
} while(cur.resType < RESOURCE_QUANTITY && !(cur.resVal=rs[cur.resType]));
if(cur.resType >= RESOURCE_QUANTITY)
cur.resVal = -1;
}
Res::ResourceSet::nziterator::nziterator(const ResourceSet &RS)
: rs(RS)
{
cur.resType = 0;
cur.resVal = rs[0];
if(!valid())
advance();
}

123
lib/ResourceSet.h Normal file
View File

@ -0,0 +1,123 @@
#pragma once
#include"../global.h"
typedef si32 TResource;
namespace Res
{
class ResourceSet;
bool canAfford(const ResourceSet &res, const ResourceSet &price); //can a be used to pay price b
enum ERes
{
WOOD = 0, MERCURY, ORE, SULFUR, CRYSTAL, GEMS, GOLD, MITHRIL
};
//class to be representing a vector of resource
class ResourceSet : public std::vector<int>
{
public:
DLL_EXPORT ResourceSet();
#define scalarOperator(OPSIGN) \
DLL_EXPORT ResourceSet operator OPSIGN(const TResource &rhs) const \
{ \
ResourceSet ret = *this; \
for(int i = 0; i < size(); i++) \
ret[i] = at(i) OPSIGN rhs; \
\
return ret; \
}
#define vectorOperator(OPSIGN) \
DLL_EXPORT ResourceSet operator OPSIGN(const ResourceSet &rhs) const \
{ \
ResourceSet ret = *this; \
for(int i = 0; i < size(); i++) \
ret[i] = at(i) OPSIGN rhs[i]; \
\
return ret; \
}
#define opEqOperator(OPSIGN, RHS_TYPE) \
DLL_EXPORT ResourceSet& operator OPSIGN ## =(const RHS_TYPE &rhs) \
{ \
return *this = *this OPSIGN rhs; \
}
scalarOperator(+)
scalarOperator(-)
scalarOperator(*)
scalarOperator(/)
opEqOperator(+, TResource)
opEqOperator(-, TResource)
opEqOperator(*, TResource)
vectorOperator(+)
vectorOperator(-)
opEqOperator(+, ResourceSet)
opEqOperator(-, ResourceSet)
#undef scalarOperator
#undef vectorOperator
#undef opEqOperator
//to be used for calculations of type "how many units of sth can I afford?"
DLL_EXPORT int operator/(const ResourceSet &rhs)
{
int ret = INT_MAX;
for(int i = 0; i < size(); i++)
amin(ret, at(i) / rhs[i]);
return ret;
}
// WARNING: comparison operators are used for "can afford" relation: a <= b means that foreach i a[i] <= b[i]
// that doesn't work the other way: a > b doesn't mean that a cannot be afforded with b, it's still b can afford a
// bool operator<(const ResourceSet &rhs)
// {
// for(int i = 0; i < size(); i++)
// if(at(i) >= rhs[i])
// return false;
//
// return true;
// }
template <typename Handler> void serialize(Handler &h, const int version)
{
h & static_cast<std::vector<int>&>(*this);
}
DLL_EXPORT void amax(const TResource &val); //performs amax on each element
DLL_EXPORT bool nonZero() const; //returns true if at least one value is non-zero;
DLL_EXPORT bool canAfford(const ResourceSet &price) const;
DLL_EXPORT bool canBeAfforded(const ResourceSet &res) const;
//special iterator of iterating over non-zero resources in set
class DLL_EXPORT nziterator
{
struct ResEntry
{
TResource resType, resVal;
} cur;
const ResourceSet &rs;
void advance();
public:
nziterator(const ResourceSet &RS);
bool valid();
nziterator operator++();
nziterator operator++(int);
const ResEntry& operator*() const;
const ResEntry* operator->() const;
};
};
}
typedef Res::ResourceSet TResources;

View File

@ -173,6 +173,7 @@
<ClCompile Include="CCreatureSet.cpp" />
<ClCompile Include="CDefObjInfoHandler.cpp" />
<ClCompile Include="CFileUtility.cpp" />
<ClCompile Include="CGameInterface.cpp" />
<ClCompile Include="CGameState.cpp" />
<ClCompile Include="CGeneralTextHandler.cpp" />
<ClCompile Include="CHeroHandler.cpp" />
@ -188,6 +189,7 @@
<ClCompile Include="NetPacksLib.cpp" />
<ClCompile Include="RegisterTypes.cpp" />
<ClCompile Include="..\stdafx.cpp" />
<ClCompile Include="ResourceSet.cpp" />
<ClCompile Include="VCMI_Lib.cpp" />
</ItemGroup>
<ItemGroup>
@ -203,6 +205,7 @@
<ClInclude Include="CCreatureSet.h" />
<ClInclude Include="CDefObjInfoHandler.h" />
<ClInclude Include="CFileUtility.h" />
<ClInclude Include="CGameInterface.h" />
<ClInclude Include="CGameState.h" />
<ClInclude Include="CGeneralTextHandler.h" />
<ClInclude Include="CHeroHandler.h" />
@ -223,6 +226,7 @@
<ClInclude Include="map.h" />
<ClInclude Include="NetPacks.h" />
<ClInclude Include="RegisterTypes.h" />
<ClInclude Include="ResourceSet.h" />
<ClInclude Include="VCMI_Lib.h" />
<ClInclude Include="VCMIDirs.h" />
</ItemGroup>

View File

@ -724,7 +724,6 @@ void Mapa::loadTown( CGObjectInstance * &nobj, const unsigned char * bufor, int
nce->town = nt;
nce->name = readString(bufor,i);
nce->message = readString(bufor,i);
nce->resources.resize(RESOURCE_QUANTITY);
for(int x=0; x < 7; x++)
{
nce->resources[x] = readNormalNr(bufor,i);
@ -1885,7 +1884,6 @@ void Mapa::readEvents( const unsigned char * bufor, int &i )
{
ne->message +=bufor[i]; ++i;
}
ne->resources.resize(RESOURCE_QUANTITY);
for(int k=0; k < 7; k++)
{
ne->resources[k] = readNormalNr(bufor,i); i+=4;

View File

@ -15,6 +15,7 @@
#endif
#include "ConstTransitivePtr.h"
#include "ResourceSet.h"
/*
* map.h, part of VCMI engine
@ -211,7 +212,7 @@ class DLL_EXPORT CMapEvent
{
public:
std::string name, message;
std::vector<si32> resources; //gained / taken resources
TResources resources; //gained / taken resources
ui8 players; //affected players
ui8 humanAffected;
ui8 computerAffected;

View File

@ -924,11 +924,7 @@ void CGameHandler::newTurn()
}
n.res[i->first] = i->second.resources;
// SetResources r;
// r.player = i->first;
// for(int j=0;j<RESOURCE_QUANTITY;j++)
// r.res[j] = i->second.resources[j];
BOOST_FOREACH(CGHeroInstance *h, (*i).second.heroes)
{
if(h->visitedTown)
@ -955,7 +951,6 @@ void CGameHandler::newTurn()
}
}
}
//n.res.push_back(r);
}
// townID, creatureID, amount
std::map<si32, std::map<si32, si32> > newCreas;//creatures that needs to be added by town events
@ -987,7 +982,7 @@ void CGameHandler::newTurn()
n.res[player][(**j).town->primaryRes] ++;;
}
}
n.res[player][6] += (**j).dailyIncome();
n.res[player][Res::GOLD] += (**j).dailyIncome();
}
handleTownEvents(*j, n, newCreas);
if (vstd::contains((**j).builtBuildings, 26))
@ -2211,9 +2206,7 @@ bool CGameHandler::buildStructure( si32 tid, si32 bid, bool force /*=false*/ )
{
SetResources sr;
sr.player = t->tempOwner;
sr.res = gs->getPlayer(t->tempOwner)->resources;
for(int i=0;i<b->resources.size();i++)
sr.res[i]-=b->resources[i];
sr.res = gs->getPlayer(t->tempOwner)->resources - b->resources;
sendAndApply(&sr);
}
@ -2315,8 +2308,7 @@ bool CGameHandler::recruitCreatures( si32 objid, ui32 crid, ui32 cram, si32 from
//recruit
SetResources sr;
sr.player = dst->tempOwner;
for(int i=0;i<RESOURCE_QUANTITY;i++)
sr.res[i] = gs->getPlayer(dst->tempOwner)->resources[i] - (c->cost[i] * cram);
sr.res = gs->getPlayer(dst->tempOwner)->resources - (c->cost * cram);
SetAvailableCreatures sac;
sac.tid = objid;
@ -2361,8 +2353,10 @@ bool CGameHandler::upgradeCreature( ui32 objid, ui8 pos, ui32 upgID )
assert(obj->hasStackAtSlot(pos));
UpgradeInfo ui = gs->getUpgradeInfo(obj->getStack(pos));
int player = obj->tempOwner;
const PlayerState *p = getPlayer(player);
int crQuantity = obj->stacks[pos]->count;
int newIDpos= vstd::findPos(ui.newID, upgID);//get position of new id in UpgradeInfo
TResources totalCost = ui.cost[newIDpos] * crQuantity;
//check if upgrade is possible
if( (ui.oldID<0 || newIDpos == -1 ) && complain("That upgrade is not possible!"))
@ -2372,24 +2366,14 @@ bool CGameHandler::upgradeCreature( ui32 objid, ui8 pos, ui32 upgID )
//check if player has enough resources
for (std::set<std::pair<int,int> >::iterator j=ui.cost[newIDpos].begin(); j!=ui.cost[newIDpos].end(); j++)
{
if(gs->getPlayer(player)->resources[j->first] < j->second*crQuantity)
{
complain("Cannot upgrade, not enough resources!");
return false;
}
}
if(!p->resources.canAfford(totalCost))
COMPLAIN_RET("Cannot upgrade, not enough resources!");
//take resources
for (std::set<std::pair<int,int> >::iterator j=ui.cost[newIDpos].begin(); j!=ui.cost[newIDpos].end(); j++)
{
SetResource sr;
sr.player = player;
sr.resid = j->first;
sr.val = gs->getPlayer(player)->resources[j->first] - j->second*crQuantity;
sendAndApply(&sr);
}
SetResources sr;
sr.player = player;
sr.res = p->resources - totalCost;
sendAndApply(&sr);
//upgrade creature
changeStackType(StackLocation(obj, pos), VLC->creh->creatures[upgID]);
@ -2854,8 +2838,8 @@ bool CGameHandler::hireHero(const CGObjectInstance *obj, ui8 hid, ui8 player)
const PlayerState *p = gs->getPlayer(player);
const CGTownInstance *t = gs->getTown(obj->id);
//common prconditions
if( p->resources[6]<2500 && complain("Not enough gold for buying hero!")
//common preconditions
if( p->resources[Res::GOLD]<2500 && complain("Not enough gold for buying hero!")
|| getHeroCount(player, false) >= 8 && complain("Cannot hire hero, only 8 wandering heroes are allowed!"))
return false;
@ -2905,8 +2889,8 @@ bool CGameHandler::hireHero(const CGObjectInstance *obj, ui8 hid, ui8 player)
SetResource sr;
sr.player = player;
sr.resid = 6;
sr.val = p->resources[6] - 2500;
sr.resid = Res::GOLD;
sr.val = p->resources[Res::GOLD] - 2500;
sendAndApply(&sr);
if(t)
@ -3775,30 +3759,22 @@ void CGameHandler::handleTimeEvents()
//give resources
SetResources sr;
sr.player = player;
sr.res = pinfo->resources;
sr.res = pinfo->resources + ev->resources;
//prepare dialog
InfoWindow iw;
iw.player = player;
iw.text << ev->message;
for (int i=0; i<ev->resources.size(); i++)
{
if(ev->resources[i]) //if resource is changed, we add it to the dialog
{
// If removing too much resources, adjust the
// amount so the total doesn't become negative.
if (sr.res[i] + ev->resources[i] < 0)
ev->resources[i] = -sr.res[i];
if(ev->resources[i]) //if non-zero res change
{
iw.components.push_back(Component(Component::RESOURCE,i,ev->resources[i],0));
sr.res[i] += ev->resources[i];
}
}
iw.components.push_back(Component(Component::RESOURCE,i,ev->resources[i],0));
}
if (iw.components.size())
{
sr.res.amax(0); // If removing too much resources, adjust the amount so the total doesn't become negative.
sendAndApply(&sr); //update player resources if changed
}
@ -3839,21 +3815,24 @@ void CGameHandler::handleTownEvents(CGTownInstance * town, NewTurn &n, std::map<
|| (ev->humanAffected && pinfo->human) ) )
{
// dialog
InfoWindow iw;
iw.player = player;
iw.text << ev->message;
for (int i=0; i<ev->resources.size(); i++)
if(ev->resources[i]) //if resource had changed, we add it to the dialog
{
int was = n.res[player][i];
n.res[player][i] += ev->resources[i];
n.res[player][i] = std::max<si32>(n.res[player][i], 0);
if(ev->resources.nonZero())
{
TResources was = n.res[player];
n.res[player] += ev->resources;
n.res[player].amax(0);
for (int i=0; i<ev->resources.size(); i++)
if(ev->resources[i] && pinfo->resources[i] != n.res[player][i]) //if resource had changed, we add it to the dialog
iw.components.push_back(Component(Component::RESOURCE,i,n.res[player][i]-was[i],0));
}
if(pinfo->resources[i] != n.res[player][i]) //if non-zero res change
iw.components.push_back(Component(Component::RESOURCE,i,n.res[player][i]-was,0));
}
for(std::set<si32>::iterator i = ev->buildings.begin(); i!=ev->buildings.end();i++)
if ( !vstd::contains(town->builtBuildings, *i))
{
@ -4018,8 +3997,8 @@ bool CGameHandler::buildBoat( ui32 objid )
SetResources sr;
sr.player = obj->o->tempOwner;
sr.res = gs->getPlayer(obj->o->tempOwner)->resources;
sr.res[0] -= 10;
sr.res[6] -= 1000;
sr.res[Res::WOOD] -= 10;
sr.res[Res::GOLD] -= 1000;
sendAndApply(&sr);
//create boat