1 // _________ __ __
2 // / _____// |_____________ _/ |______ ____ __ __ ______
3 // \_____ \\ __\_ __ \__ \\ __\__ \ / ___\| | \/ ___/
4 // / \| | | | \// __ \| | / __ \_/ /_/ > | /\___ |
5 // /_______ /|__| |__| (____ /__| (____ /\___ /|____//____ >
6 // \/ \/ \//_____/ \/
7 // ______________________ ______________________
8 // T H E W A R B E G I N S
9 // Stratagus - A free fantasy real time strategy game engine
10 //
11 /**@name action_explore.cpp - The explore action. */
12 //
13 // (c) Copyright 1998-2019 by Lutz Sammer, Jimmy Salmon and Talas
14 //
15 // This program is free software; you can redistribute it and/or modify
16 // it under the terms of the GNU General Public License as published by
17 // the Free Software Foundation; only version 2 of the License.
18 //
19 // This program is distributed in the hope that it will be useful,
20 // but WITHOUT ANY WARRANTY; without even the implied warranty of
21 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 // GNU General Public License for more details.
23 //
24 // You should have received a copy of the GNU General Public License
25 // along with this program; if not, write to the Free Software
26 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27 // 02111-1307, USA.
28 //
29
30 //@{
31
32 /*----------------------------------------------------------------------------
33 -- Includes
34 ----------------------------------------------------------------------------*/
35
36 #include "stratagus.h"
37
38 #include "action/action_explore.h"
39
40 #include "animation.h"
41 #include "iolib.h"
42 #include "map.h"
43 #include "pathfinder.h"
44 #include "script.h"
45 #include "tile.h"
46 #include "ui.h"
47 #include "unit.h"
48 #include "unittype.h"
49 #include "video.h"
50
51 /*----------------------------------------------------------------------------
52 -- Functions
53 ----------------------------------------------------------------------------*/
54
GetExplorationTarget(const CUnit & unit,Vec2i & dest)55 static void GetExplorationTarget(const CUnit &unit, Vec2i &dest)
56 {
57 int triesLeft = Map.NoFogOfWar ? 0 : 3;
58 CMapField *field;
59 const CPlayer &player = *unit.Player;
60 dest.x = SyncRand(Map.Info.MapWidth - 1) + 1;
61 dest.y = SyncRand(Map.Info.MapHeight - 1) + 1;
62
63 while (triesLeft > 0) {
64 field = Map.Field(dest);
65 if (field && !field->playerInfo.IsExplored(player))
66 return; // unexplored, go here!
67 dest.x = SyncRand(Map.Info.MapWidth - 1) + 1;
68 dest.y = SyncRand(Map.Info.MapHeight - 1) + 1;
69 --triesLeft;
70 }
71 }
72
NewActionExplore(const CUnit & unit)73 /* static */ COrder *COrder::NewActionExplore(const CUnit &unit)
74 {
75 Vec2i dest;
76 GetExplorationTarget(unit, dest);
77 Assert(Map.Info.IsPointOnMap(dest));
78
79 COrder_Explore *order = new COrder_Explore();
80
81 order->goalPos = dest;
82 return order;
83 }
84
85
Save(CFile & file,const CUnit & unit) const86 /* virtual */ void COrder_Explore::Save(CFile &file, const CUnit &unit) const
87 {
88 file.printf("{\"action-explore\",");
89
90 if (this->Finished) {
91 file.printf(" \"finished\", ");
92 }
93 file.printf(" \"tile\", {%d, %d},", this->goalPos.x, this->goalPos.y);
94 file.printf(" \"range\", %d,", this->Range);
95
96 if (this->WaitingCycle != 0) {
97 file.printf(" \"waiting-cycle\", %d,", this->WaitingCycle);
98 }
99 file.printf("}");
100 }
101
ParseSpecificData(lua_State * l,int & j,const char * value,const CUnit & unit)102 /* virtual */ bool COrder_Explore::ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit)
103 {
104 if (!strcmp(value, "waiting-cycle")) {
105 ++j;
106 this->WaitingCycle = LuaToNumber(l, -1, j + 1);
107 } else if (!strcmp(value, "range")) {
108 ++j;
109 this->Range = LuaToNumber(l, -1, j + 1);
110 } else if (!strcmp(value, "tile")) {
111 ++j;
112 lua_rawgeti(l, -1, j + 1);
113 CclGetPos(l, &this->goalPos.x , &this->goalPos.y);
114 lua_pop(l, 1);
115 } else {
116 return false;
117 }
118 return true;
119 }
120
IsValid() const121 /* virtual */ bool COrder_Explore::IsValid() const
122 {
123 return true;
124 }
125
Show(const CViewport & vp,const PixelPos & lastScreenPos) const126 /* virtual */ PixelPos COrder_Explore::Show(const CViewport &vp, const PixelPos &lastScreenPos) const
127 {
128 const PixelPos pos1 = vp.TilePosToScreen_Center(this->goalPos);
129
130 Video.DrawLineClip(ColorGreen, lastScreenPos, pos1);
131 Video.FillCircleClip(ColorBlue, pos1, 2);
132 return pos1;
133 }
134
UpdatePathFinderData(PathFinderInput & input)135 /* virtual */ void COrder_Explore::UpdatePathFinderData(PathFinderInput &input)
136 {
137 input.SetMinRange(0);
138 input.SetMaxRange(this->Range);
139 const Vec2i tileSize(0, 0);
140 input.SetGoal(this->goalPos, tileSize);
141 }
142
143
Execute(CUnit & unit)144 /* virtual */ void COrder_Explore::Execute(CUnit &unit)
145 {
146 if (unit.Wait) {
147 if (!unit.Waiting) {
148 unit.Waiting = 1;
149 unit.WaitBackup = unit.Anim;
150 }
151 UnitShowAnimation(unit, unit.Type->Animations->Still);
152 unit.Wait--;
153 return;
154 }
155 if (unit.Waiting) {
156 unit.Anim = unit.WaitBackup;
157 unit.Waiting = 0;
158 }
159
160 switch (DoActionMove(unit)) {
161 case PF_FAILED:
162 this->WaitingCycle = 0;
163 break;
164 case PF_UNREACHABLE:
165 // Increase range and try again
166 this->WaitingCycle = 1;
167 this->Range++;
168 break;
169
170 case PF_REACHED:
171 {
172 this->WaitingCycle = 1;
173 this->Range = 0;
174 // pick a new place to explore
175 GetExplorationTarget(unit, this->goalPos);
176 }
177 break;
178 case PF_WAIT:
179 {
180 // Wait for a while then give up
181 this->WaitingCycle++;
182 if (this->WaitingCycle == 5) {
183 this->WaitingCycle = 0;
184 this->Range = 0;
185 // pick a new place to explore
186 GetExplorationTarget(unit, this->goalPos);
187
188 unit.pathFinderData->output.Cycles = 0; //moving counter
189 }
190 }
191 break;
192 default: // moving
193 this->WaitingCycle = 0;
194 break;
195 }
196
197 if (!unit.Anim.Unbreakable) {
198 if (AutoAttack(unit) || AutoRepair(unit) || AutoCast(unit)) {
199 this->Finished = true;
200 }
201 }
202 }
203
204 /**
205 ** Get goal position
206 */
GetGoalPos() const207 /* virtual */ const Vec2i COrder_Explore::GetGoalPos() const
208 {
209 const Vec2i invalidPos(-1, -1);
210 if (goalPos != invalidPos) {
211 return goalPos;
212 }
213 if (this->HasGoal()) {
214 return this->GetGoal()->tilePos;
215 }
216 return invalidPos;
217 }
218
219 //@}
220