Crossfire Server, Trunk  R20513
CRECombatSimulator.cpp
Go to the documentation of this file.
1 #include "CRECombatSimulator.h"
2 #include "CREPixmap.h"
3 
4 extern "C" {
5 #include <global.h>
6 #include <sproto.h>
7 }
8 
10 {
11  QGridLayout* layout = new QGridLayout(this);
12  int line = 0;
13 
14  layout->addWidget(new QLabel(tr("First fighter:"), this), line, 0);
15  myFirst = new QComboBox(this);
16  layout->addWidget(myFirst, line++, 1);
17 
18  layout->addWidget(new QLabel(tr("Second fighter:"), this), line, 0);
19  mySecond = new QComboBox(this);
20  layout->addWidget(mySecond, line++, 1);
21 
22  const archetype* arch = first_archetype;
23  while (arch)
24  {
25  if (arch->head == NULL && QUERY_FLAG(&arch->clone, FLAG_MONSTER))
26  {
27  myFirst->addItem(CREPixmap::getIcon(arch->clone.face->number), arch->name, qVariantFromValue((void*)arch));
28  mySecond->addItem(CREPixmap::getIcon(arch->clone.face->number), arch->name, qVariantFromValue((void*)arch));
29  }
30  arch = arch->next;
31  }
32 
33  layout->addWidget(new QLabel(tr("Number of fights:"), this), line, 0);
34  myCombats = new QSpinBox(this);
35  myCombats->setMinimum(1);
36  myCombats->setMaximum(10000);
37  layout->addWidget(myCombats, line++, 1);
38 
39  layout->addWidget(new QLabel(tr("Maximum number of rounds:"), this), line, 0);
40  myMaxRounds = new QSpinBox(this);
41  myMaxRounds->setMinimum(1);
42  myMaxRounds->setMaximum(10000);
43  myMaxRounds->setValue(500);
44  layout->addWidget(myMaxRounds, line++, 1);
45 
46  myResultLabel = new QLabel(tr("Combat result:"), this);
47  myResultLabel->setVisible(false);
48  layout->addWidget(myResultLabel, line++, 0, 1, 2);
49  myResult = new QLabel(this);
50  myResult->setVisible(false);
51  layout->addWidget(myResult, line++, 0, 1, 2);
52 
53  QDialogButtonBox* box = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Close, Qt::Horizontal, this);
54  layout->addWidget(box, line++, 0, 1, 2);
55  connect(box, SIGNAL(rejected()), this, SLOT(reject()));
56  connect(box, SIGNAL(accepted()), this, SLOT(fight()));
57 
58  setWindowTitle(tr("Combat simulator"));
59 }
60 
62 {
63 }
64 
65 void CRECombatSimulator::fight(const archetype* first, const archetype* second)
66 {
67  int limit = myMaxRounds->value();
68  object* obfirst = object_create_arch((archetype*)first);
69  object* obsecond = object_create_arch((archetype*)second);
70  tag_t tagfirst = obfirst->count;
71  tag_t tagsecond = obsecond->count;
72 
73  // make a big map so large monsters are ok in map
74  mapstruct* test_map = get_empty_map(50, 50);
75 
76  // insert shifted for monsters like titans who have parts with negative values
77  obfirst = object_insert_in_map_at(obfirst, test_map, NULL, 0, 12, 12);
78  obsecond = object_insert_in_map_at(obsecond, test_map, NULL, 0, 37, 37);
79 
80  while (limit-- > 0 && obfirst->stats.hp >= 0 && obsecond->stats.hp >= 0)
81  {
82  if (obfirst->speed_left > 0) {
83  --obfirst->speed_left;
84  monster_do_living(obfirst);
85  if (obfirst->stats.hp > myFirstMaxHp)
86  myFirstMaxHp = obfirst->stats.hp;
87 
88  attack_ob(obsecond, obfirst);
89  if (object_was_destroyed(obsecond, tagsecond))
90  break;
91  if (obsecond->stats.hp < mySecondMinHp && obsecond->stats.hp > 0)
92  mySecondMinHp = obsecond->stats.hp;
93  }
94 
95  if (obsecond->speed_left > 0) {
96  --obsecond->speed_left;
97  monster_do_living(obsecond);
98  if (obsecond->stats.hp > mySecondMaxHp)
99  mySecondMaxHp = obsecond->stats.hp;
100 
101  attack_ob(obfirst, obsecond);
102  if (object_was_destroyed(obfirst, tagfirst))
103  break;
104  if (obfirst->stats.hp < myFirstMinHp && obfirst->stats.hp > 0)
105  myFirstMinHp = obfirst->stats.hp;
106  }
107 
108  if (obfirst->speed_left <= 0)
109  obfirst->speed_left += FABS(obfirst->speed);
110  if (obsecond->speed_left <= 0)
111  obsecond->speed_left += FABS(obsecond->speed);
112  }
113 
114  if (limit > 0)
115  {
116  if (obfirst->stats.hp < 0)
118  else
120  }
121 
122  if (!object_was_destroyed(obfirst, tagfirst))
123  {
124  object_remove(obfirst);
125  object_free2(obfirst, 0);
126  }
127  if (!object_was_destroyed(obsecond, tagsecond))
128  {
129  object_remove(obsecond);
130  object_free2(obsecond, 0);
131  }
132  free_map(test_map);
133 }
134 
136 {
137  QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
138 
139  myFirstVictories = 0;
140  mySecondVictories = 0;
141 
142  const archetype* first = (const archetype*)myFirst->itemData(myFirst->currentIndex()).value<void*>();
143  const archetype* second = (const archetype*)mySecond->itemData(mySecond->currentIndex()).value<void*>();
144 
145  /*
146  * Set min and max hp here, in case a monster doesn't ever get attacked
147  * Example as of the time of writing is cherub vs. cherub
148  * without this fix, the first cherub had maxhp of 10000 and minhp of -1
149  *
150  * So, temporaily create the objects to then determine what the maxhp is for
151  * each object from the archetypes.
152  */
153  object* obfirst = object_create_arch((archetype*)first);
154  object* obsecond = object_create_arch((archetype*)second);
155 
156  myFirstMinHp = obfirst->stats.maxhp;
157  myFirstMaxHp = obfirst->stats.maxhp;
158  mySecondMinHp = obsecond->stats.maxhp;
159  mySecondMaxHp = obsecond->stats.maxhp;
160 
161  /*
162  * Then, free the objects since this is done.
163  */
164  object_free2(obfirst, 0);
165  object_free2(obsecond, 0);
166 
167  int count = myCombats->value();
168  while (count-- > 0)
169  {
170  fight(first, second);
171  }
172 
173  myResult->setText(tr("Draw: %1 fights\n%2 victories: %3 (max hp: %4, min hp: %5)\n%6 victories: %7 (max hp: %8, min hp: %9)")
174  .arg(myCombats->value() - myFirstVictories - mySecondVictories)
175  .arg(first->name).arg(myFirstVictories).arg(myFirstMaxHp).arg(myFirstMinHp)
176  .arg(second->name).arg(mySecondVictories).arg(mySecondMaxHp).arg(mySecondMinHp));
177 
178  myResultLabel->setVisible(true);
179  myResult->setVisible(true);
180 
181  QApplication::restoreOverrideCursor();
182 }
mapstruct * get_empty_map(int sizex, int sizey)
Creates and returns a map of the specific size.
Definition: map.c:874
#define FABS(x)
Decstations have trouble with fabs()...
Definition: define.h:22
int attack_ob(object *op, object *hitter)
Simple wrapper for attack_ob_simple(), will use hitter&#39;s values.
Definition: attack.c:903
object clone
An object from which to do object_copy()
Definition: object.h:470
#define object_was_destroyed(op, old_tag)
Checks if an object still exists.
Definition: object.h:68
mapstruct * test_map
Definition: comet_perf.c:73
Global type definitions and header inclusions.
void free_map(mapstruct *m)
Frees everything allocated by the given mapstructure.
Definition: map.c:1694
The archetype structure is a set of rules on how to generate and manipulate objects which point to ar...
Definition: object.h:465
int16_t hp
Hit Points.
Definition: living.h:39
uint16_t number
This is the image id.
Definition: face.h:15
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
Same as object_insert_in_map() except it handle separate coordinates and do a clean job preparing mul...
Definition: object.c:1921
int16_t maxhp
Max hit points.
Definition: living.h:40
float speed_left
How much speed is left to spend this round.
Definition: object.h:329
struct archt * head
The main part of a linked object.
Definition: object.h:468
uint32_t tag_t
Object tag, unique during the whole game.
Definition: object.h:12
float speed
The overall speed of this object.
Definition: object.h:328
#define QUERY_FLAG(xyz, p)
Definition: define.h:225
object * object_create_arch(archetype *at)
Create a full object using the given archetype.
Definition: arch.c:736
static QIcon getIcon(int faceNumber)
Definition: CREPixmap.cpp:27
tag_t count
Unique object number for this object.
Definition: object.h:299
living stats
Str, Con, Dex, etc.
Definition: object.h:368
void object_free2(object *ob, int flags)
Frees everything allocated by an object, removes it from the list of used objects, and puts it on the list of free objects.
Definition: object.c:1391
struct archt * next
Next archetype in a linked list.
Definition: object.h:467
#define FLAG_MONSTER
Will attack players.
Definition: define.h:245
void monster_do_living(object *op)
For a monster, regenerate hp and sp, potentially clear scared status.
Definition: monster.c:500
This is a game-map.
Definition: map.h:325
const New_Face * face
Face with colors.
Definition: object.h:332
EXTERN archetype * first_archetype
First archetype.
Definition: global.h:122
const char * name
More definite name, like "generate_kobold".
Definition: object.h:466
void object_remove(object *op)
This function removes the object op from the linked list of objects which it is currently tied to...
Definition: object.c:1654
Definition: main.c:88