File: README.development

package info (click to toggle)
widelands 1%3A15-3squeeze2
  • links: PTS, VCS
  • area: main
  • in suites: squeeze
  • size: 206,508 kB
  • ctags: 12,956
  • sloc: cpp: 96,550; python: 2,636; ada: 849; sh: 269; objc: 254; makefile: 180
file content (103 lines) | stat: -rw-r--r-- 5,147 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
README for developers
---------------------

This file is simply a collection of thoughts, useful pieces of
information, etc.


Parallel Simulation
-------------------
The game logic is supposed to be affected only by the following factors:
- the pseudo RNG (which is completely determined by the initial seed)
- the starting conditions
- the sequence of player commands sent to the Cmd_Queue

As long as the gameplay logic stays the same (no code changes / no changes
to conf files), and the above factors remain the same, the outcome must
be the same.

This property of the Widelands game logic is extremely important for two
reasons:
- Multiplayer by parallel simulation:
  Every host keeps the complete state of the simulation in memory, and only
  player commands are exchanged to keep network traffic low. The properties
  above guarantuee that there is no desync.
- Demo recording
  By creating a savegame followed by a sequence of player commands, it is
  possible to create a demo recording of a game (similar to Age of Empires,
  for example)


Why std::set<SomePointer*> is a bad idea
----------------------------------------
Well, actually it's only a bad idea in the game logic, here's why.

std::set<Foo*> uses pointer comparisons to sort the set. Pointers aren't
system-independent (in fact, they might even differ from one run to the
next on the same system). Therefore, this construct *must not* be used in
the game logic.
Similar constructs are affected as well. Basically, never use pointer
arithmetics for decision-making.

A word about triggers and events
--------------------------------
Here i'll talk very shortly about triggers and events and how they are implemented.

Triggers are exactly what they sound like: Simple triggers (switches) which can 
either be on or off. Triggers are checked periodically in the cmdqueue if they
are set or not. The cmdqueue makes sure that each trigger is checked at least
once every second. So this is the problem with the triggers. For example,
you have set a Time Trigger, which should go to on after 2 seconds. Now, it
really gets set after 20-21 seconds; same: it could take up to 1 seconds before
an event occurs that should be tackled by one trigger; even worse: it could take
up to number_of_triggers_the_event_needs_to_be_set seconds. So the way triggers are
checked may change in the future when this proofs as to slow.

If you want to implement a new trigger, here is what to do. First, make sure
that: 
  1) if your trigger sets/unsets itself in the check function, make sure that it 
     stays set/unset, even if it's condition changes again until it is reset by 
     some event. Than it behave on a check like expected
  2) if your trigger triggers only once through the whole game, make sure that
     your reset function assert(0)s and that it's check function never ever
     changes the state again after this first time.

Ok, now the steps to implement a new Trigger:
  1) Add its id in src/trigger_ids.h (TRIGGER_<YOUR_TRIGGER_NAME>)
  2) Add its description, name and id into TRIGGER_DESCRIPTIONS[] in
      src/trigger_factor.cc, update also the functions ther
  3) Derive a class Trigger_<Your_Trigger_Name> from Trigger (own header and
     source file, trigger_<your_name_here>.[h|cc]
  4) Create the Menu class as a modal window (no move, no other actions allowed
     while open) in
        src/editor/ui_menus/trigger_<your_trigger_name_here>_option_menu.[cc|h]
And you're done. Orientate yourself while implementing on the other triggers,
especially the file read/write functions have to write certain data in certain
order (especially ID and TRIGGER_VERSION of your trigger)

Events are also what they sound like: Something happens in the game. Events can
be nearly everything you can imagine (and programm 8) ): change of terrain, new
land conquered, unhide areas, warp some wares/workers, let the computer attack
or show a message box to the interactive user are just some possibilitys.
Events depend on triggers, each event can have one or more triggers attached to
it, whenever a trigger gets set, all events look at their triggers, and if all
are in the state the event needs, the event runs itself. If the event can't rerun
again (a one timer), it deletes itself and frees all triggers that he needed, 
if the triggers aren't referenced anymore, they also get deleted.

What to do to implement an Event:
   1) Add its id in src/event_ids.h 
   2) Add its description in src/event_factory.cc and update the functions 
      there.
   3) Derive a class Event_<Your Event Name> from class Event (own header
      and source file)
      make sure that you proper handle your resources,
        memory stuff should be freed in destructor
        trigger should be released in cleanup and reinitialized/freed
        in reinitialize_own(). if all triggers are already released in 
        reinitialize own, cleanup must detect this and not release them 
        again
   4) Create the Option-Menu class as a modal window in
         src/editor/ui_menus/event_<event name here>.[h|cc]
And that's all. Orientat yourself on the already implemented classes.