OpenClonk
C4MassMover.cpp
Go to the documentation of this file.
1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 1998-2000, Matthes Bender
5  * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
6  * Copyright (c) 2009-2016, The OpenClonk Team and contributors
7  *
8  * Distributed under the terms of the ISC license; see accompanying file
9  * "COPYING" for details.
10  *
11  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
12  * See accompanying file "TRADEMARK" for details.
13  *
14  * To redistribute this file separately, substitute the full license texts
15  * for the above references.
16  */
17 
18 /* Move liquids in the landscape using individual transport spots */
19 
20 #include "C4Include.h"
21 #include "landscape/C4MassMover.h"
22 
23 #include "c4group/C4Components.h"
24 #include "control/C4Record.h"
25 #include "landscape/C4Material.h"
26 #include "landscape/C4Landscape.h"
27 #include "lib/C4Random.h"
28 
29 // Note: creation optimized using advancing CreatePtr, so sequential
30 // creation does not keep rescanning the complete set for a free
31 // slot. (This had caused extreme delays.) This had the effect that
32 // MMs created by another MM being executed were oftenly executed
33 // within the same frame repetitiously leading to long distance mass
34 // movement in no-time. To avoid this, set execution is done in
35 // opposite direction. We now have have smoothly running masses in
36 // a mathematical triangular shape with no delays! Since masses are
37 // running slower and smoother, overall MM counts are much lower,
38 // hardly ever exceeding 1000. October 1997
39 
41 {
42  Default();
43 }
44 
46 {
47  Clear();
48 }
49 
51 {
52 
53 }
54 
56 {
57  C4MassMover *cmm;
58  // Init counts
59  Count=0;
60  // Execute & count
61  for (int32_t speed = 2; speed>0; speed--)
62  {
63  cmm = &(Set[C4MassMoverChunk-1]);
64  for (int32_t cnt = 0; cnt<C4MassMoverChunk; cnt++,cmm--)
65  if (cmm->Mat!=MNone)
66  { Count++; cmm->Execute(); }
67  }
68 }
69 
70 bool C4MassMoverSet::Create(int32_t x, int32_t y, bool fExecute)
71 {
72  if (Count == C4MassMoverChunk) return false;
74  {
75  C4RCMassMover rc;
76  rc.x=x; rc.y=y;
77  AddDbgRec(RCT_MMC, &rc, sizeof(rc));
78  }
79  int32_t cptr=CreatePtr;
80  do
81  {
82  cptr++;
83  if (cptr>=C4MassMoverChunk) cptr=0;
84  if (Set[cptr].Mat==MNone)
85  {
86  if (!Set[cptr].Init(x,y)) return false;
87  CreatePtr=cptr;
88  if (fExecute) Set[cptr].Execute();
89  return true;
90  }
91  }
92  while (cptr!=CreatePtr);
93  return false;
94 }
95 
97 {
98 }
99 
100 bool C4MassMover::Init(int32_t tx, int32_t ty)
101 {
102  // Out of bounds check
103  if (!Inside<int32_t>(tx,0,::Landscape.GetWidth()-1) || !Inside<int32_t>(ty,0,::Landscape.GetHeight()-1))
104  return false;
105  // Check mat
106  Mat=GBackMat(tx,ty);
107  x=tx; y=ty;
108  ::MassMover.Count++;
109  return (Mat!=MNone);
110 }
111 
113 {
114  if (Config.General.DebugRec)
115  {
116  C4RCMassMover rc;
117  rc.x=x; rc.y=y;
118  AddDbgRec(RCT_MMD, &rc, sizeof(rc));
119  }
120  ::MassMover.Count--;
121  Mat=MNone;
122 }
123 
125 {
126  int32_t tx,ty;
127 
128  // Lost target material
129  if (GBackMat(x,y)!=Mat) { Cease(); return false; }
130 
131  // Check for transfer target space
133  tx=x; ty=y;
134  if (!::Landscape.FindMatPath(tx,ty,+1,pMat->Density,pMat->MaxSlide))
135  {
136  // Contact material reaction check: corrosion/evaporation/inflammation/etc.
137  if (Corrosion(+0,+1) || Corrosion(-1,+0) || Corrosion(+1,+0))
138  {
139  // material has been used up
141  return true;
142  }
143 
144  // No space, die
145  Cease(); return false;
146  }
147 
148  // do check at this pos for conversion check
149  /* if (Corrosion(0,0))
150  {
151  // material has been used up by conversion
152  ::Landscape.ExtractMaterial(x,y);
153  return true;
154  }*/
155 
156  // Transfer mass
157  int32_t mat = ::Landscape.ExtractMaterial(x,y,false);
158  if (Random(10))
159  ::Landscape.InsertDeadMaterial(mat, tx, ty);
160  else
161  ::Landscape.InsertMaterial(mat, &tx, &ty, 0, 1); // modifies tx/ty to actual insertion position
162 
163  // Create new mover at target
164  ::MassMover.Create(tx,ty,!Random(3));
165 
166  return true;
167 }
168 
169 bool C4MassMover::Corrosion(int32_t dx, int32_t dy)
170 {
171  // check reaction map of massmover-mat to target mat
172  int32_t tmat=GBackMat(x+dx,y+dy);
174  if (pReact)
175  {
176  C4Real xdir=Fix0, ydir=Fix0;
177  if ((*pReact->pFunc)(pReact, x,y, x+dx,y+dy, xdir,ydir, Mat,tmat, meeMassMove, nullptr))
178  return true;
179  }
180  return false;
181 }
182 
184 {
185  int32_t cnt;
186  for (cnt=0; cnt<C4MassMoverChunk; cnt++) Set[cnt].Mat=MNone;
187  Count=0;
188  CreatePtr=0;
189 }
190 
192 {
193  int32_t cnt;
194  // Consolidate
195  Consolidate();
196  // Recount
197  Count=0;
198  for (cnt=0; cnt<C4MassMoverChunk; cnt++)
199  if (Set[cnt].Mat!=MNone)
200  Count++;
201  // All empty: delete component
202  if (!Count)
203  {
204  hGroup.Delete(C4CFN_MassMover);
205  return true;
206  }
207  // Save set
208  if (!hGroup.Add(C4CFN_MassMover,Set,Count*sizeof(C4MassMover)))
209  return false;
210  // Success
211  return true;
212 }
213 
215 {
216  // clear previous
217  Clear(); Default();
218  size_t iBinSize,iMoverSize=sizeof(C4MassMover);
219  if (!hGroup.AccessEntry(C4CFN_MassMover,&iBinSize)) return false;
220  if ((iBinSize % iMoverSize)!=0) return false;
221  // load new
222  Count = iBinSize / iMoverSize;
223  if (!hGroup.Read(Set,iBinSize)) return false;
224  return true;
225 }
226 
228 {
229  // Consolidate set
230  int32_t iSpot,iPtr,iConsolidated;
231  for (iSpot=-1,iPtr=0,iConsolidated=0; iPtr<C4MassMoverChunk; iPtr++)
232  {
233  // Empty: set new spot if needed
234  if (Set[iPtr].Mat==MNone)
235  {
236  if (iSpot==-1) iSpot=iPtr;
237  }
238  // Full: move down to empty spot if possible
239  else if (iSpot!=-1)
240  {
241  // Move to spot
242  Set[iSpot]=Set[iPtr];
243  Set[iPtr].Mat=MNone;
244  iConsolidated++;
245  // Advance empty spot (as far as ptr)
246  for (; iSpot<iPtr; iSpot++)
247  if (Set[iSpot].Mat==MNone)
248  break;
249  // No empty spot below ptr
250  if (iSpot==iPtr) iSpot=-1;
251  }
252  }
253  // Reset create ptr
254  CreatePtr=0;
255 }
256 
258 {
259  Consolidate();
260 }
261 
263 {
264  Clear();
265  Count=rSet.Count;
266  CreatePtr=rSet.CreatePtr;
267  for (int32_t cnt=0; cnt<C4MassMoverChunk; cnt++) Set[cnt]=rSet.Set[cnt];
268 }
269 
#define C4CFN_MassMover
Definition: C4Components.h:76
C4Config Config
Definition: C4Config.cpp:930
const int32_t MNone
Definition: C4Constants.h:177
C4Landscape Landscape
int32_t GBackMat(int32_t x, int32_t y)
Definition: C4Landscape.h:219
C4MassMoverSet MassMover
const int32_t C4MassMoverChunk
Definition: C4MassMover.h:23
C4MaterialMap MaterialMap
Definition: C4Material.cpp:974
@ meeMassMove
Definition: C4Material.h:38
uint32_t Random()
Definition: C4Random.cpp:43
const C4Real Fix0
Definition: C4Real.h:312
void AddDbgRec(C4RecordChunkType eType, const void *pData, int iSize)
Definition: C4Record.cpp:32
@ RCT_MMD
Definition: C4Record.h:61
@ RCT_MMC
Definition: C4Record.h:60
int32_t DebugRec
Definition: C4Config.h:63
C4ConfigGeneral General
Definition: C4Config.h:255
Definition: C4Real.h:59
bool Read(void *buffer, size_t size) override
Definition: C4Group.cpp:1430
bool AccessEntry(const char *wildcard, size_t *size=nullptr, char *filename=nullptr, bool needs_to_be_a_group=false)
Definition: C4Group.cpp:2104
bool Add(const char *filename, const char *entry_name)
Definition: C4Group.cpp:1621
bool Delete(const char *files, bool recursive=false)
Definition: C4Group.cpp:1645
int32_t GetWidth() const
int32_t ExtractMaterial(int32_t fx, int32_t fy, bool distant_first)
bool FindMatPath(int32_t &fx, int32_t &fy, int32_t ydir, int32_t mdens, int32_t mslide) const
bool InsertDeadMaterial(int32_t mat, int32_t tx, int32_t ty)
int32_t GetHeight() const
bool InsertMaterial(int32_t mat, int32_t *tx, int32_t *ty, int32_t vx=0, int32_t vy=0, bool query_only=false)
int32_t x
Definition: C4MassMover.h:29
bool Corrosion(int32_t dx, int32_t dy)
bool Execute()
int32_t Mat
Definition: C4MassMover.h:29
int32_t y
Definition: C4MassMover.h:29
bool Init(int32_t tx, int32_t ty)
void Copy(C4MassMoverSet &rSet)
int32_t Count
Definition: C4MassMover.h:43
C4MassMover Set[C4MassMoverChunk]
Definition: C4MassMover.h:46
bool Load(C4Group &hGroup)
bool Create(int32_t x, int32_t y, bool fExecute=false)
Definition: C4MassMover.cpp:70
bool Save(C4Group &hGroup)
int32_t CreatePtr
Definition: C4MassMover.h:44
int32_t Density
Definition: C4Material.h:92
int32_t MaxSlide
Definition: C4Material.h:104
C4MaterialReaction * GetReactionUnsafe(int32_t iPXSMat, int32_t iLandscapeMat)
Definition: C4Material.h:191
C4Material * Map
Definition: C4Material.h:169
C4MaterialReactionFunc pFunc
Definition: C4Material.h:47