Design & Concepts
We have decided to implement the program following a two-layer
model. There will be a core layer, encapsulating and modelling
the state of the game. This core layer will be accessed by game
layer, which is responible for playing the game, i.e., it will
receive information and give commands to the core layer via a
well-defined interface.
This layer contains the data structures representing the whole
Free Orion universe, containing
information about all the stars and planets, ships, etc., and
also the players and their interrelations. These data structures
are supplemented with basic methods for their management, which
are not transparent to the actual game-play. General functions
like the code evaluating the turn commands (see The Turn Concept) are located in this
layer as well. More concepts of the core layer will be discussed
in the sections API Concepts and API Requirements.
Implementation: The core layer will be implemented in the
java package org.freeorion.api. Its central class
is the Controller, which gives access to all other
relevant objects within the core layer. The objects of the core
layer will provide methods to access the relevant data and to
manipulate the objects of the core layer according to the rules
of the game.
There will be different kinds of game layers:
-
A graphical user interface (GUI). This will allow a user to
view the state of the core engine via an intuitive display and
to perform actions permitted by the game. A GUI shall be
included in Free Orion.
-
A computer driven player. This will be a program
implementing some strategy to play the game. It should be
possible to extend Free Orion by
adding additional computer players later on.
Implementation: A class claims to be a game layer by
implementing the org.freeorion.api.GameLayer
interface. We assume that the classes of the game layer are not
part of the org.freeorion.api package, instead they
form a seperate package of their own. So the GUI is implemented
in the package org.freeorion.gui and a computer
player driven by artificial stupidity may be placed in a package
like org.freeorion.stupid.
Free Orion is a game to be played by
multiple players (real players via a graphical interface or
computer driven players). Each player has her own restricted
view on the world. We respond to this request by assigning to
each player a personalized restricted copy of the core engine.
This copy will be call a Free Orion
Client (realized be the class
ClientController).
On the other hand there will be one central instance of the core
engine, containing an (unrestricted) view of the whole
world. This core engine will be called the Free Orion Server (implemented as class
ServerController).
Free Orion is a turn-based game. Each
player can perform a (theoretically unlimited ;-)) number of
actions in each turn. Turns of differrent players are assumed
to happen simultaneously, so one player should not be aware of the
effects of another player's actions before the beginning of the next
turn. This means that the evaluation of the players' actions needs
to be delayed.
This requirement is answered by the Client and Server concept and a
mechanism called the turn command list: During a turn the
player will manipulate her world, that is she will send commands
to the client assigned to her. The client will execute the
commands, but it will also collect them in the turn command
list. When all players have finished their turns, all the
clients will send their turn command lists to the server which
will evaluate them. The server then has an up-to-date picture
of the universe and will send this to the clients.
Each turn can be divided up into different phases or
states. These states determine what kinds of actions are
valid at that time. We have two sets of states, one for the
client and one for the server:
The client cycles through the following states:
-
INIT: The client accepts initialization commands
from the server.
-
READY_TO_START: The client has been initialized and
is
waiting for a "start turn" command from the server.
-
RUNNING: The client accepts input from the game layer.
This state is terminated when the "end turn" command
is sent by the game layer.
-
FINISHED_TURN: The client has finished its turn and is
ready to send the turn command list to the server.
On the other hand, the server knows the following states:
-
INIT: The server is initializing.
-
SENDING_TURN_DATA: The server is sending turn data
to the clients.
-
WAITING: The server is waiting for all clients to
finish their turns.
-
RUNNING: The server receives the turn command lists
from the clients and executes them.
-
END_OF_TURN_ACTION: The server performs end of turn
actions (see Turn Evaluation).
Implementation: The current state of a
Controller can be accessed by its
getStatus()-method.
In this section we collect some concepts that do not fit in any
other section of this document.
Most of the classes in the org.freeorion.api
package are derived from
org.freeorion.api.OrionObject. The instances of
those classes have a unique ID, by which they can be identified,
and a reference to the Controller to which the are
assigned. While the objects of a client may change from turn to
turn, their IDs will never change. [FIXME: So if a game layer
wants to store objects to access them in the next turn the
objects IDs!]
The classes and methods provided by the API can be divided into
public and internal ones. The public methods can be accessed by
an (external) GameLayer. This implies that they
have to provide protection against misuse. Internal methods are
only invoked by other parts of the API. They are local to the
org.freeorion.api package and their names are
syntactically marked by a leading underscore (example:
Ship._move()).
Most of the (public) methods should only be used in certain
stages during program execution. The Controller
provides a status that can be used to decide if the invocation
of a method is valid or not (see The State
Concept).
This section lists requirements we expect the API to implement
before we may see it as completed.
In what follows, we give a list of all commands the API should
provide to a game layer. Most of these actions can only be
performed if some condition is fulfilled. The API must check
check these restrictions before it can accept the action to be
performed.
- move colonist: move a colonist from a given colony and given
job to another colony and/or another job
Restrictions: At least one colonist must
stay in each colony and some "colonists" like natives and androids
cannot be moved at all or cannot change their job.
- change production: set the current production of a colony to
another item
Restrictions: It is only possible to
select an item for production that is covered by the technologies
available to the player. Buildings may be built only once per planet.
Other things like ships, colony bases, or terraforming need special
attention. The production cannot be changed after a "buy production"
action has been performed in the colony in that turn.
Note: Changes to the whole production
queue as well as ship designs may be buffered by the Game layer.
Refitting ships can be taken (by the Game layer?) as a compound
scrap ship / build ship (i.e., change production) action
(with special attention to the amount of money generated
from the scrapping (none) and the amount of work that
needs to be spent (less than that necessary for a newly
produced ship)).
- buy production: buy the currently produced item in a colony
Restrictions: The player needs to have
the funds necessary to do this.
- scrap building: scrap a building in one of the player's
colonies in exchange for money
Restrictions: Only one building can be
scrapped per colony and turn.
- set ship destination: set the destination of a ship to a given
star
Restrictions: The ship has to be within
the command range of the player and the star within the range
determined by the type of fuel cells available to the player.
Note: selecting specific planets as
targets for colony or outpost ships should be handled by the Game
layer
- scrap ship: scrap a ship in order to receive money and
possibly technologies
Restrictions: Nothing will be gained if
the ship has not been orbiting a star system occupied by the player.
- hire leader: hire a leader that is currently offering to join
this player
Restrictions: The player needs the
necessary funds.
- move leader: send a leader to a star system or ship
Restrictions: (The leader and system or
ship must be controlled by this player.)
- fire leader: remove a leader from one's staff
Restrictions: (The leader must be a
member of the player's staff.)
- sign treaty: sign a trade, research, peace, non-agression,
alliance, or tribute treaty with another player, or declare war on her
Restrictions: Both players have to agree
on the treaty (exception: war). A treaty may not be signed more than
once.
- cancel treaty: revoke any of the aforementioned treaties
(except war)
Restrictions: The treaty must have been
signed before.
- make gift: make a gift to another player - this can be money,
technology, or a whole star system
Restrictions: The player making the gift
must own enough money / the technology / the star system. Capitol
systems or systems out of reach of the recipient may not be donated.
Note: The exchange of technologies and
most demand actions can be implemented through this action. However,
some demand actions (stop espionage, declare war on, break alliance)
do not work this way.
- move spy: move a spy from one player to another
Restrictions: The player must have a spy
at the source location. There is an upper limit of 63 for the number of
spies at any location.
- change spies' orders: change the orders of spies targeted at
another player (spy, sabotage, hide)
Restrictions: - none -
- change research: change the current research goal
Restrictions: Only applications from the
respective next technological levels may be selected. Uncreative
players cannot choose an application.
- change tax rate: set the tax rate to 0, 10, 20, 30, 40, or 50
percent
Restrictions: - none -
- scrap freighter: reduce the number of freighters at one's
disposal
Restrictions: - none -
Note: Check whether freighters currently
employed to relocate colonists are exempt from destruction.
- attack antares: order a ship to attack Antares
Restrictions: The ships have to be in a
star system with a colony that has a dimensional gate.
- attack player: order a ship to attack another player's ships
or colonies
Restrictions: The attacker and the
defendant must be in the same star system.
Note: This action comprises a whole
number of actions really, including the conquest or even the utter
destruction of a colony. As the results of these actions only become
apparent after the opposing sides have met in combat, the attack player
action needs to be evaluated in between the evaluations of other
actions (see the section on Turn Evaluation below).
However, there are some user actions which we consider not to affect
the turn command list.
They should be handeled internally by the game layer:
- attack enemy fleet:
XXX:
- change production list:
The production list can be local to the user interface. When there
is no item currently being produced, then the first item from the
list will be selected.
- change ship design:
FIXME: This section is not in a sane state yet, so you
should better ignore it!
When all the players have put together their turn command
lists the orion core engine will start the
evaluation. This will be done performing the following steps:
- Destroy freighters:
Should be performed before they are used (move colonist, food)
- Move colonist:
This should be done before food, production and research is evaluated,
because it affects their actual values.
Also the colonists should be moved before a colony is transfered to
another player or attacked by enemies.
- Transfer colonies and technologies (based on diplomatic actions)
This will cancel the actual production, so it should be done before
(XXX or after?) the production is performed.
- Perform production and research:
This should be done simultaneously because new technology should
not affect the speed of production and new buildings should not affect
the research in this turn.
However it should be done before food consumption and combat, so
that new achievements can be used there.
- Calculate food production/consumption:
Should be done before the population growth is calculated.
But it may be done after new buildings/freighters are produced so that
the player can benefit from them.
- Do population growth:
- Move ships:
The ships have to be moved before the combat check is performed.
- Check for combats:
In situations where combats are possible, the combatants have to be
asked if they wish to fight (user
interaction). If a combat takes place this may be the
source of a bundle of further actions:
- delete some ships
- change the ownership of ships (when they have been entered)
- set ships' destination (ships retreating should be sent were
they come from)
- destroy buildings on the planet
- change ownership of the planet
- transfer some technologies
- Set ships' destination:
Ships which are outside the (new) range of a player should be sent
to the next star were the player is present.
- Do spying:
Should be done after combat.
- Calculate money:
- Create random events