Archive for the ‘Uncategorized’ Category

About

Thursday, June 26th, 2008

Welcome!

This is the website for my Allefant project hosted on SourceForge. It is a collection of various games I wrote over the years for short game programming competitions, such competitions usually taking about 2 days to create the complete game (code as well as art). The first such game I made was Allefant back in the year 2000. Some of the games also were worked on afterwards and polished a bit, so they are actually playable. Most are little more than a tech demo though. They are all open source.

Woosls/GUI

Saturday, January 1st, 2000

User Interface

This will most notably carry the simplicity. There are no dialogs or any sort of GUI elements, except a fixed bar of buttons to the left. The left bottom will have an overview map. The right part will be the main screen, with the game map.

Left clicking will be the way to interact with buttons, and to perform actions in the main screen. Right clicking will be used to scroll.

Buttons

* Following up on the simplicity, there is a fixed layout for all buttons. There are 4 tabs, each has 8 buttons. for 8 panels. The 4 tabs are: Buildings, Settings, Statistics, System

* Buildings: A button for each building to build it with the next mouse click into the map. Each of the 8 panels holds 4 building buttons.

* Settings: The 8 panels are: Waypoint, Carrier Priorities, Food Priorities, Industry Priorities, …
* Waypoint: This panel allows commands for the currently selected waypoint. This includes:
* Send geologist
* Top priority
* Stop work
* Abandon
* Carrier: This panel allows to change the priority in which item orders are handled. It has an icon of each possible item, and there order can be modified.
* Food: Distribution of fish/bread/ham to coal/iron/gold/stone mine, water to baker/pig farm, grain to mill/pig farm.
* Industry: Distribution of boards to construction sites or boat builder, logs to woodcutter/char burner, coal to gold/iron melter, weapon/tool smith, iron bars to weapon/tool smith

Woosls/Buildings

Saturday, January 1st, 2000

Buildings

  • Orders for buildings and waypoints can be given any time, but they don’t do anything by themselves. Only when a road is built between two of them, a unit is assigned to that road. Upon arrival, a carrier will choose a home in the middle of the two waypoints, and start carrying. A builder will choose the non-waypoints as its home, and start building. Most will choose a home and start doing their profession.
  • Buildings:
    • woodcutter hut {*}
    • forester hut {*}
    • stonemason hut {*}
    • farm {*}
    • fisherman hut {*}
    • sawmill {*}
    • mill {*}
    • bakery {*}
    • pig ranch {*}
    • butchery {*}
    • gold smeltery {*}
    • iron smeltery {*}
    • weapon smithy {o}
    • tool smithy {o}
    • boat builder {o}
    • gold mine {*}
    • coal mine {*}
    • iron mine {*}
    • stone mine {*}
    • water works {*}
    • charcoal site {*}
    • waypoint {*}
    • storage {*}
    • castle {*}
    • tower {*}
    • vineyard {o}
    • monastery {o}
    • residence {*}
    • tent {*}
    • camp {*}
  • A carrier goes home if one of its waypoints is destroyed. Other units can deal with their second waypoint getting destroyed. As soon as a new road is connected to their home, they will adjust their second waypoint.

Woosls/Items

Saturday, January 1st, 2000

Items

  • The following items are planned:
    • log {*}
    • board {*}
    • stone {*}
    • grain {*}
    • flour {*}
    • bread {*}
    • fish {*}
    • pig {*}
    • ham {*}
    • gold ore {*}
    • iron ore {*}
    • coal {*}
    • gold bar {*}
    • iron bar {*}
    • sword {*}
    • boat {o}
    • hammer {*}
    • pliers {*}
    • saw {*}
    • axe {*}
    • pick axe {*}
    • scythe {*}
    • fishing pole {*}
    • bucket {*}
  • All items have a destination path tagged to them. Carriers will look for items at both of their waypoints, and transport them accordingly.
  • For each item type, there will be a list of providers, and users. Each
    provider and user will fill in the amount they have in stock, and the amount
    required. For example, a sawmill might have 3 boards in stock, and a
    construction site might need 3 boards. Therefore, a path is searched in the
    roads net, and the boards are tagged with it.

    This can deal well enough with permanent request. E.g. a sawmill can store 6
    logs, so it will only have a request placed for the missing storage. Once it has
    ordered 7 logs, it will be removed from the users list, and then only order a
    new log again when it has processed one of the 6 logs first.

    Providers are castles and storage halls, and also other producers. E.g. a
    sawmill may provide up to 6 boards on its associated waypoint.

    Castles and storage halls also are users for all goods - but as a special
    case, only for goods from actual produces, and only if nobody needs them.

    Priorities can be set if the same good is needed by different professions.
    E.g. coal can be develivered to both the iron and the gold melter. This is
    handled by a global priority system. The user can set a ratio, e.g. 1:2 for
    coal which goes to gold and iron melter. A global counter of delivered goods
    is used to keep the ratio at the set value. When the ratio is changed,
    counters are all reset, and the ratio is used for all subsequent deliveries.

    Apart from the priorities, orders are processed on a first-in, first-out
    basis. Once an order to process is found, the nearest source of the item in
    question is found, and the item is tagged with the path.

  • The priorities could be realized by assigning each newly arrived order a priority.
    For example, assume fish is set to priority 10 for gold mines, and priority 1 for iron
    mines. If now a gold mine orders a fish, that order is inserted with priority 10, the
    other with 1. (If priority for something is set to 0, the order isn’t even processed.)

    When processing orders, now only those with priority 10 are considered. All others
    only have their priority increased by 1. Therefore, if there’s a big stock of fish
    available, and gold and iron mine will constantly place orders, the gold mine will
    have it’s orders all processed at one, while the iron mine’s orders will be
    processed only for each 10th time a gold mine order is processed.

Woosls/Network

Saturday, January 1st, 2000

Network

General

Networked games run on each client, and use a server for synchronization. The server will do nothing but accepting commands from the clients, and then broadcasting the commands again. But it will make sure that the exact same commands and in the same order arrive for each client, in the same game tick.

A client must run synchronized. That is, it will have a function game.tick, which is run every time the server sends a TICK command. This probably would be fast enough with happening only around 10 times a second - so will need a way to separate game logic from actual animation. For example, if an animation is one second long, that would be only 10 game ticks. But still, it might move something by 100 pixels pixel-by-pixel.

Commands

Initial client commands:

  • * PLAY name - Ask to join the game.
  • * STAR size, seed - The game host starts the game on a map with the given parameters.
  • * TOAI id - The given player is an AI player (host only)
  • * READ - This client is ready

Initial server commands:
* WELC player/seed/size - A newly joining clients gets this. The first is the player number it gets assigned, and then information so it can create a new random map from the given random number generator seed and map size.

  • * PLAY id, name - A new player joins the game.
  • * STAR size, seed - Game starts. After this, no more new players can join.
  • * TOAI id - given player is an AI player
  • * READ id - given player is ready

Client commands:

  • * BUIL type/x/y - Place a building of the given type at the given location.
  • * ROAD x/y/x/y… - Build a road over all the given positions.
  • * REMB x/y - Destroy building at x/y.
  • * REMR x/y - Destroy the road leading over x/y, or starting there, if it is the only.
  • * GEOL x/y - Send out a geologist.
  • * TOOL a/b/c/… - Modify production settings.
  • * RECR a/b/c/… - Modify recruitment settings.
  • * DIST a/b/c/… - Modify distribution settings.
  • * ATTA x/y - Attack given location.

Server commands:

  • * BUIL id/type/x/y
  • * ROAD id/x/y/x/y…
  • * REMB id/x/y
  • * REMR id/x/y
  • * GEOL id/x/y
  • * TOOL id/a/b/c/…
  • * RECR id/a/b/c/…
  • * DIST id/a/b/c/…
  • * ATTA id/x/y
  • * LEFT id - A player left the game.
  • * TICK n - Next game tick marker.

Lag

Lag hopefully isn’t that big a problem. Even your own action will go to the server before being processed, but nothing in this game should be time critical.

Cheating

A central server is used, so cheating attempts by clients could be detected there (e.g. if anything is different than on the host player, we know there has been cheating). A cheating player could be disconnected.

Actually, even for clients it should be possible to detect cheating. Any packet in the chain of packets not possible would mean cheating (or desynchronization). So basically, any tampering with the game state will lead to desynchronization, and the game will end.

Another form of cheating would be to access hidden information. For example, a client could run with the whole map visible, and could eavesdrop on any settings and commands issued by other clients. There’s not much that can be done to prevent this.

Woosls/Military

Saturday, January 1st, 2000

Military

Being an RTS game, sooner or later you will encounter enemies. To attack them, barracks must be built. They can hold multiple military units, which will attack enemies in the vincinity. A challenged unit will not run away, but await the attacker once challenged. To give not too much advantage to the attacker that way, fights are always one-on-one.

Woosls/Map

Saturday, January 1st, 2000

Map

Just a simple square-grid of hexagons.

Maps are currently created randomly.

Resources

Fish, Water, Coal, Stone, Iron, Gold

Woosls/Roads

Saturday, January 1st, 2000

Roads/Waypoints

  • The base of a settlement is the roads net:
  • Each building and each waypoint is a node in the roads net.
  • Each active unit has a road. For carriers, this road connects two waypoints.
    For all others, it connects a waypoint and their workplace.
  • Pathes are only found inside the road system. If a unit goes from point A to
    point B, both A and B must be nodes in the roads system. Same if an item is
    shipped from A to B. Found pathes are cached on the assumption that the path
    finder might take up lots of performance. Any modification to the roads
    system invalidates the complete cache though.
  • Items can only be transported along the roads.
  • When a road is removed, not much happens, just:
  • It is erased from the map.
  • It is removed from the roads map, any cached pathes are invalidated.
  • The unit assigned to the road is sent home.

New pathes calculated from now on will not consider the road - but there may
still be units walking a path containing the removed road, and goods tagged
with a path over the now missing part.

In the former case, units will try to find another path.
/!\ TODO: /!\ details? what if no other path? what if a unit is on a road while it is
removed?

In the case of items, the items should be retagged with a new path, or sent
back, and a replacement order placed.
TODO: details? how is it detected?

Pathes

  • Caching - the same path may get used multiple times before waypoints are removed/added -
    so might want to cache pathes. Removing or adding any road invalidates all
    cached pathes.

Woosls/Code

Saturday, January 1st, 2000

General

The Woosls code is written in Python, and follows the Python style guide. That is, 4 space indentation, no spaces around ( and ), and so on.

When using Python for small scripts, you never need care much about code organization, it simply will be readable. For a project like this, there are some self-imposed guidelines:

* Put all variables at proper place, that is, local, class level, or module level. Python has no global variables, so the problems of C++ with that can’t arise.

* Next, initialize all variables in the __init__ function of the class. This somehow violates the ability to have fully dynamic objects, but for Woosls, it is good as documentation. For example, when the game is saved and reloaded, it’s enough to check that every variable in the __init__ methods is saved/reloaded. Of course the pickle module could be used in that specific case, bu still - it’s nice to have an overview of all variables, even if usually you just add properties to an object where they arise.

* Never make a file with more than 1000 lines. 500 lines already is really bad. And creating a file of 1 line for a very simple class is ok. The reason is, this serves again as documentation. If each unit class has its file, then everything is clear. Of course you could just put 3 or 4 units inherited from another in one file.. but there’s no advantage.

* Related to the previous, never put many unrelated source files into the same directory. E.g. all units go into their own directory.

That’s about it, I may add more later. But it’s all Python code, so there really shouldn’t be much possibility to mess up completely, like in most other languages who ”’even ignore whitespace”’ |)

main.py

This does several things (maybe should split it?):
* Startup code
* Run the main event loop
* Dispatch events and ticks to server, client, GUI
* Hold global accessible items, e.g. the screen or the current client, so they can be accessed by other modules without having to pass around references everywhere

map.py

The map module simply contains the representation of the hexagon map.

game.py

The game module contains the complete game state. This means map and players.

server.py

The server module has the game server. It handles all client requests and sends out the game ticks.

client.py

This is where user input is collected and transformed into requests to the server. Replies by the server are received and passed on to the game module.

player.py

This module describes a player. A player has units, a roads net, various settings and other things.

unit.py

Implementation of a single unit.

Woosls/Maingame

Saturday, January 1st, 2000

Main game

Setting up a game

There are two phases when starting a game. First, all players must join. Each new client will receive information to create the map. At some point, the host player starts the game, and now the server will start providing game ticks for all clients. The game runs synchronized on each client.

The above means, only minimal information must be traded between clients over the server. But it also means, a new player cannot simply join at a later point, since it would need the whole game state. If a player loses connection, this means, it’s not possible for him or her to rejoin. One possibility to deal with it would be, safe and abort the game as soon as the loss of a player is detected. Now, if the savegame is transfered to the player who lost connection, this saved game can be continued.

Starting a saved game is similiar to starting a new game, just now it is assumed that each player has a savegame of the same state. When the host starts the game and the server starts ticking, the game will continue synchronized for all from the saved state. Maybe could also make each client build a checksum of their state, and if there’s a mismatch to the host checksum, ask to transfer the savegame from the host (or auto-transfer it).

Gameplay

The user mostly will do two things:

* Order buildings
* Create roads

When a building is ordered on a position of the map, it is immediately placed, but as 0% finished. And the order for sending out a builder unit to this construction site is scheduled.

Buildings can only be built in owned territory. To increase the territory, towers must be built.

If territories would overlap, /!\ TODO /!\ this must be resolved. Maybe the first owner keeps it - that way, it is an advantage to be somewhere first. If the newer tower would get it all, it would be too hard to defend own land. Another possibility would be to split in the middle - so it’s possible to gain enemy territory, but only a bit. Because of the roads net, overlapping land can’t be co-owned by both. Another possibility would be to make it no-man’s-land.

Also see Military.