Implement a new version of an existing module

Implement a new version of an existing module

Anyone is free at any time to implement a module which already exists. Of course, there is no point in having multiple versions of straightforward modules like Board or Group, but less straightforward modules such as Shape or Scoring might benefit from having multiple implementations. Some reasons for implementing a module that already exists include: Here is a list of the things that a developer would need to do in order to implement an existing module. This example assumes that a new implementation of the Shape module is being created called nnshape.
  1. Make sure that you have read and understood the requirements and high-level design documents. It is hard to overstate the importance of this. It would be silly to spend six months implementing a module and then find out that it needs to be redesigned, where a few hours up front could have saved that wasted effort. You should be able to answer the following questions before proceeding:
  2. Read the Coding Standards
  3. Make an nnshape directory in the org/moyoman/module/shape directory.
  4. Create an NNShape class which extends the Module class, and implements the Shape interface.
  5. Override the generateMove() method. This is the method that identifies good and bad moves.
  6. Override the makeMove() method. This is the method that indicates that a move was made. Update internal data structures accordingly.
  7. Override the getDebugTypes() method.
  8. Override the getDebugInformation() method. This should return one Debug object for each type returned by the getDebugTypes() method. At least one Debug object must be generated.
  9. Override the getRequiredModulesList() method. This method indicates which other modules this module uses the output from.
  10. Override the clone() method. See an advanced Java book for more details on this. This is important, because the module will be cloned whenever another module uses its results.
  11. Run the Module admin tool to add NNShape to the list of Shape modules, and make sure that it is rated first. You can also use the Mode admin tool to create a user defined mode where NNShape is the first Shape module.

Read the documentation

The Moyoman software will become very large it is to achieve its goal of being a strong Go playing program. In order to allow for many developers to create modules independently, there must be strict rules on how a module interacts with the rest of the system. Make sure that you understand this before you start development.

Read the coding standards

This document explains some of the specific things to avoid in developing a module.

Create an nnshape directory in the org/moyoman/module/shape directory

This is where your classes go. Of course, only one class can extend the Module class, but you may wish to organize your code as multiple classes. The extra classes which do not implement the Shape interface should not have any public methods. An exception is where a module has multiple interfaces. For example, the Groups module type has Groups and SingleGroup interfaces, so one class will extend Groups and the other SingleGroup. Still, any other classes in the Groups implementation will not have public methods.

Create an NNShape class.

The NNShape class will extend the Module class, and implement the Shape interface. Before implementing this class, you will need to answer the following questions:
  1. Is the module stateless or stateful?
  2. What debug objects are going to be created, and when are they valid?

Is the module stateless or stateful?

The NNShape module might remember which moves cause good and bad shape and do an incremental update, or it might recompute the data from scratch on every move. The developer should have a clear understanding of which approach he is going to take before starting.

What debug objects are going to be created?

The module must return at least one debug object. The developer needs to determine what debug objects he is going to return, and whether they are valid after the other player has moved last, or only when this player has moved last. For example, if an incremental update is done on each move, then the debug object showing good and bad shapes might always be accurate. On the other hand, if the analysis is done from scratch, then the debug object would only show good or bad shapes when the program made the last move.

Override the generateMove() method

This method is what does the analysis for the given board position when it is the computer players turn to move. All appropriate analysis should be done, and any information that the debug objects need as well.

Override the makeMove() method

If incremental analysis is being done, then each time that this method is called, then the appropriate data structures must be updated by the last move made. If analysis is done from scratch each time that generateMove() is called, then this method may not have much to do, except for clearing out the debug objects if necessary.

Override the getDebugTypes() method

This method returns the types of debug objects that it creates.

Override the getDebugInformation() method.

Return the Debug objects that your module creates. Note that if the computer play has not moved last, then some of these debug objects may not be valid. They can be returned without any information set, or just the valid ones can be returned.

Override the getRequiredModuleList() method

This allows the framework to know what modules will be needed by your module. The same modules are passed to the generateMove() and makeMove() methods.

Implement the clone() method

Whenever a module is passed to generateMove() or makeMove() it was cloned from the original module. Therefore, the clone() method will be used frequently. It is important to make sure that you understand how cloning works, because this is a common source of errors, and it is not always obvious during testing that this is the cause of any bugs that occur.

Run the module admin tool

In order to provide flexibility and to reduce dependencies between modules as much as possible, the configuration files determine which module implementations are actually run. You need to configure the software so that your NNShape module is actually being run. It would be an easy to make mistake to think that your module was running when in fact it was another shape module. You can easily check this by looking at the logs/info file.