Python Development

From FreeOrionWiki
Revision as of 19:11, 7 December 2015 by Dilvish (Talk | contribs) (AI state in save file: added info re __setstate__ and save game compatibility)

Jump to: navigation, search

This page will be devoted to matters relating to python development in general for the FreeOrion project, including the general boost::python interface. A separate page is devoted to details specifically regarding the AI Python API. Other topics relating more specifically to the AI will be covered at AI_Development, and topics relating more specifically to universe creation will be covered at Universe_Creation. A good understanding of the Free_Orion_Content_Script_(FOCS) will also likely be very helpful since the use of python in FreeOrion closely relates to scripted content.


Python version

Supported python version is 2.7

Code style

C++ API use camelCase style

Python code should be written using general python style according to PEP8 also usefull to read google recommendations


Extend C+ API in python

In some cases it is more easy and effective to extend interface of c++ objects from python. For example string representation of object.

This code located in file default\AI\freeorion_debug\extend_free_orion_AI_interface.py

PS. Add __repr__ and __str__ methods to objects as soon as you need it.


AI state in save file

Instance of AIState is stored as pickled string in save game.

UniverseObject instances should not be stored in AIState, use id instead.

Adding or removing AIState attributes can break save compatibility. If you're not entirely sure how to handle it one option is to not fully remove them, leave them with comment to remove, to make breaks less frequent. When adding attributes or changing their names, compatibility can be broken because some of the new code will try to use attributes that the saved object won't have. To deal with this, a custom __setstate__ method can be specified, which will be called during the unpickling process and which can add default values for the newly added attributes. For example, the following method could be added to the AIstate class to provide default values for some new dictionary attributes (keep in mind, this is just for unpickling saved games; default values also need to be provided in __init__):

   def __setstate__(self, state_dict):
       self.__dict__.update(state_dict) # update attributes
       for dict_attrib in ['qualifyingColonyBaseTargets',
                           'qualifyingOutpostBaseTargets',
                           'qualifyingTroopBaseTargets',
                           'planet_status',
                           'diplomatic_logs']:
           if dict_attrib not in state_dict:
               self.__dict__[dict_attrib] = {}

Debugging

Internal

To access chat commands you need to choose send all (default behavior) or select first AI

Send help to chat window.

You will got instruction how to work with it. start <id> will start debug mode with selected id stop will finish debug mode

To run start you need that this AI was selected (don't select any AI and all will work fine)

Most used variables already imported to scope with short name (e:empire, u: universe, ai: aiState)

Chat window does not support multiline input. Use semicolon as line separator

Use short user name. In examples I use ($) as short name for user.

This chat works like python shell. You can assign variables, print result and do almost all you want.

   $ x = 1
   $ x
   1
   $ print x + 3
   4
   $ e.playerName
   'AI_3'

See more possibilities: Tips and tricks


External

For windows remove Python27.* from installed game folder to use system python(don't forget to install it)

PyDev

Pydev manual

To open console: If you want to use the interactive console in the context of a breakpoint, a different approach would be selecting a stack frame (in the debug view) > right-clicking it > pydev > Debug Console (or you can also in the debug view create a new console view connected to the debug session for the same effect).

winpdb

winpdb


Tips and tricks

Reload module

- enter debug mode

   $ start 2

- import module to current scope

   $ import ProductionAI

- change module - reload module

   $ reload(ProductionAI)

- end turn and enjoy result

Note: Reload module that store some state will ruin the game (FreeOrionAI)

Execute file

   $ execfile('file_path')

path can be absolute or relative to current working dir

   $ import os
   $ print os.getcwd()

Python editor

 It is your choice how to edit python code. Here are some suggestions:

- PyCharm community edition

- Eclipse based.

A good IDE will help you to make fewer mistakes, and keyboard shortcuts and other IDE features can greatly speedup your development. If you are unfamiliar with using an IDE then two key features to be sure to learn are how to quickly navigate to an item's declaration (preferably with a shortcut key), and how to use its code completion feature.

Deploying code

Best way to deploy your code to game is to specify resource-dir and stringtable-filename in persistent_config file.

- navigate to game folder with Config.xml
- create persistent_config.xml
- add next text and replace repository_path to your path
  <?xml version="1.0"?>
  <XMLDoc>
  <resource-dir>repository_path/freeorion/default</resource-dir>
  <stringtable-filename>repository_pathfreeorion/default/stringtables/en.txt</stringtable-filename>
  </XMLDoc>

FAQ

- Q: This page can be better / has typo / ...
- A: Welcome to forum, lets do it better.
- Q: Which python version used?
- A: Windows: python shipped with game(2.7.3) Other system use system python.
- Q: Where does print output go?
- A: stdout and stderr redirected to logs in the game settings folder.
- Q: How do I test new code?
- A: start/load a game (changing code during gameplay will not affect a current game; the code is already in memory).