Alternatives to multiple inheritance for my architecture (NPCs in a Realtime Strategy game)?

Coding isn’t that hard actually. The hard part is to write code that makes sense, is readable and understandable. So I want to get a better developer and create some solid architecture.

So I want to do create an architecture for NPCs in a video-game. It is a Realtime Strategy game like Starcraft, Age of Empires, Command & Conquers, etc etc.. So I’ll have different kinds of NPCs. A NPC can have one to many abilities (methods) of these: Build(), Farm() and Attack().

Examples:
Worker can Build() and Farm()
Warrior can Attack()
Citizen can Build(), Farm() and Attack()
Fisherman can Farm() and Attack()

I hope everything is clear so far.

So now I do have my NPC Types and their abilities. But lets come to the technical / programmatical aspect.
What would be a good programmatic architecture for my different kinds of NPCs?

Okay I could have a base class. Actually I think this is a good way to stick with the DRY principle. So I can have methods like WalkTo(x,y) in my base class since every NPC will be able to move. But now lets come to the real problem. Where do I implement my abilities? (remember: Build(), Farm() and Attack())

Since the abilities will consists of the same logic it would be annoying / break DRY principle to implement them for each NPC (Worker,Warrior, ..).

Okay I could implement the abilities within the base class. This would require some kind of logic that verifies if a NPC can use ability X. IsBuilder, CanBuild, .. I think it is clear what I want to express.
But I don’t feel very well with this idea. This sounds like a bloated base class with too much functionality.

I do use C# as programming language. So multiple inheritance isn’t an option here. Means: Having extra base classes like Fisherman : Farmer, Attacker won’t work.

2

Composition and Interface Inheritance are the usual alternatives to classical multiple inheritance.

Everything that you described above that starts with the word “can” is a capability that can be represented with an interface, as in ICanBuild, or ICanFarm. You can inherit as many of those interfaces as you think you need.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>public class Worker: ICanBuild, ICanFarm
{
#region ICanBuild Implementation
// Build
#endregion
#region ICanFarm Implementation
// Farm
#endregion
}
</code>
<code>public class Worker: ICanBuild, ICanFarm { #region ICanBuild Implementation // Build #endregion #region ICanFarm Implementation // Farm #endregion } </code>
public class Worker: ICanBuild, ICanFarm
{
    #region ICanBuild Implementation
    // Build
    #endregion

    #region ICanFarm Implementation
    // Farm
    #endregion
}

You can pass in “generic” building and farming objects through the constructor of your class. That’s where composition comes in.

7

As other posters have mentioned a component architecture could be the solution to this problem.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>class component // Some generic base component structure
{
void update() {} // With an empty update function
}
</code>
<code>class component // Some generic base component structure { void update() {} // With an empty update function } </code>
class component // Some generic base component structure
{
  void update() {} // With an empty update function
} 

In this case extend the update function to implement whatever functionality the NPC should have.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>class build : component
{
override void update()
{
// Check if the right object is selected, resources, etc
}
}
</code>
<code>class build : component { override void update() { // Check if the right object is selected, resources, etc } } </code>
class build : component
{
  override void update()
  { 
    // Check if the right object is selected, resources, etc
  }
}

Iterating a component container and updating each component allows the specific functionality of each component to be applied.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>class npc
{
void update()
{
foreach(component c in components)
c.update();
}
list<component> components;
}
</code>
<code>class npc { void update() { foreach(component c in components) c.update(); } list<component> components; } </code>
class npc
{
  void update()
  {
    foreach(component c in components)
      c.update();
  }

  list<component> components;
}

As each type of object is wanted you could use some form of the factory pattern to construct the individual types you wanted.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>npc worker;
worker.add_component<build>();
worker.add_component<walk>();
worker.add_component<attack>();
</code>
<code>npc worker; worker.add_component<build>(); worker.add_component<walk>(); worker.add_component<attack>(); </code>
npc worker;
worker.add_component<build>();
worker.add_component<walk>();
worker.add_component<attack>();

I have always run into problems as the components get more and more complex. Keeping component complexity low (one responsibility) can help alleviate that problem.

If you define interfaces like ICanBuild then your game system has to inspect every NPC by type, which is typically frowned upon in OOP. For example: if (npc is ICanBuild).

You’re better off with:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>interface INPC
{
bool CanBuild { get; }
void Build(...);
bool CanFarm { get; }
void Farm(...);
... etc.
}
</code>
<code>interface INPC { bool CanBuild { get; } void Build(...); bool CanFarm { get; } void Farm(...); ... etc. } </code>
interface INPC
{
    bool CanBuild { get; }
    void Build(...);
    bool CanFarm { get; }
    void Farm(...);
    ... etc.
}

Then:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>class Worker : INPC
{
private readonly IBuildStrategy buildStrategy;
public Worker(IBuildStrategy buildStrategy)
{
this.buildStrategy = buildStrategy;
}
public bool CanBuild { get { return true; } }
public void Build(...)
{
this.buildStrategy.Build(...);
}
}
</code>
<code>class Worker : INPC { private readonly IBuildStrategy buildStrategy; public Worker(IBuildStrategy buildStrategy) { this.buildStrategy = buildStrategy; } public bool CanBuild { get { return true; } } public void Build(...) { this.buildStrategy.Build(...); } } </code>
class Worker : INPC
{
    private readonly IBuildStrategy buildStrategy;
    public Worker(IBuildStrategy buildStrategy)
    {
        this.buildStrategy = buildStrategy;
    }

    public bool CanBuild { get { return true; } }
    public void Build(...)
    {
        this.buildStrategy.Build(...);
    }
}

…or of course you could use a number of different architectures, like some kind of domain specific language in the form of a fluent interface for defining different types of NPCs, etc., where you build NPC types by combining different behaviors:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>var workerType = NPC.Builder
.Builds(new WorkerBuildBehavior())
.Farms(new WorkerFarmBehavior())
.Build();
var workerFactory = new NPCFactory(workerType);
var worker = workerFactory.Build();
</code>
<code>var workerType = NPC.Builder .Builds(new WorkerBuildBehavior()) .Farms(new WorkerFarmBehavior()) .Build(); var workerFactory = new NPCFactory(workerType); var worker = workerFactory.Build(); </code>
var workerType = NPC.Builder
    .Builds(new WorkerBuildBehavior())
    .Farms(new WorkerFarmBehavior())
    .Build();

var workerFactory = new NPCFactory(workerType);

var worker = workerFactory.Build();

The NPC builder could implement a DefaultWalkBehavior that could be overridden in the case of an NPC that flies but can’t walk, etc.

2

I’d put all the abilities in separate classes that inherit from Ability. Then in the unit type class have a list of abilities and other stuff like attack, defence, max health etc. Also have a unit class that has current health, location, etc. and has unit type as a member variable.

Define all unit types in a config file or a database, rather than hard coding it.

Then the level designer can easily adjust the abilities and stats of unit types without recompiling the game, and also people can write mods for the game.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật