Create new Mini-Game
The general pipeline of creating new mini-game is as follows:
graph TD
A(<a href="#be-clear-about-what-to-do">Be clear about \nwhat to do<a>) --> D(<a href="#use-gtk-tool-to-generate-basic-archive">Use gtk tool to generate basic archive</a>)
D --> F(<a href="#set-mini-game-messages-by-lua-script">Set mini-game messages by lua script</a>)
F --> E(<b><a href="#large-batch-auto-random-generation">Large batch auto random generation</a></b>)
E --> H{<a href="#mini-game-validation">Mini-Game Validation</a>}
H --> |Not Pass| J{Bug from \nCivrealm}
J --> |Yes| K[Contribute bugfix for Civrealm]
J --> |No| D
H --> |Pass| I[Create new Mini-Game successfully]
Be clear about what to do
The basic design mechanisms of mini-game are:
-
Single Goal. Don't consider multiple learning objectives at the same time, otherwise the game will become less mini after more influences are introduced.
-
Feasible Action. In the huge space of action, be clear about which actions are relevant to your goal, and avoid too many unrelated or paradoxical actions in actionable actions.
-
Computable Reward. In addition to the final score at the end of the game, the reward for each step or turn can be defined and calculated.
At the beginning of designing a mini-game, you have to answer the following questions:
-
What type of the mini-game do you want to design?
-
When does the mini-game end?
-
How to calculate the reward for each step?
-
How to set the difficulty of the game?
These questions will be given appropriate suggestions to some extent below.
Use gtk tool to generate basic archive
The tool of freeciv-gtk is provided by freeciv official team to help us design the very basic version of each mini-game. Please follow the instructions in ((https://github.com/freeciv/freeciv/tree/main/doc)) to install the tool and run it, specify the game settings and ruleset, which would be like:
After start a new game, use 'Edit -> Edit Mode' to design the scenario as you expect and then finish making an initial version of savegame. Save the edited scenario so that you can further edit or load it in the game. After that, you can continue to add messages and generate random maps based on it, which is introduced as followed.
Set mini-game messages by lua script
Warning
Donot modify sav file directly in general. Because the fields in the sav file have dependencies on each other, if you modify a field without noticing some other fields that need to be modified at the same time, it will cause the server to load the sav file unsuccessfully.
The lua script is used to send mini-game messages to the agent. Before adding the lua script for basic sav file, you need to understand the archive format of freeciv and how it defines the game state internally.
-
The suffix of the game archive file is
.sav
, and usually compressed as a compressed file with.xz
or.zst
suffix. If the archive file is compressed, you need to use the corresponding component to decompress it to get the sav file. -
In the sav file, there are many key-value structures to describe the current game state. Here, We list the main tags and their explanations:
Tag | Description |
savefile | A set of definition rules for common elements, including activity, technology, etc. |
game | The base state values of the game, such as turn, launch order and year. |
script | The script of lua. At the inherent or designed trigger points of the game, obtain the internal data of the game, calculate the custom game state values, and send out event messages. |
settings | The setting of freeciv server. |
map | The global map of world, and distribution information of resources, cities, and land development. |
player0 | The game status of a player with an id of 0, including information such as how many units and cities the player0 have. |
score0 | The scores of a player with an id of 0, including information such as total score and unhappy degree. |
research | The progress of research for each player. |
Here, we focus on the implementation of script
tag. In the sav file, the format of script
as below:
{lua code}
is the code of lua language that implements to send mini-game messages.
Firstly, you need to consider which trigger points to set during the game in order to change the status value of the mini-game, and set up the end conditions of the game. All trigger action functions can be referred to the Lua Reference manual. We list the common trigger action functions as follows:
(return) type | function name/variable | arguments | comments |
Boolean | turn_begin | (Number turn, Number year) | Trigger at each turn begining. |
Boolean | city_built | (City city) | Trigger at city built. |
Boolean | unit_lost | (Unit unit, Player loser, String reason) | Trigger at unit lost. |
Boolean | city_destroyed | (City city, Player loser, Player destroyer) | Trigger at city destroyed. |
In addition, we developed the following trigger action function to enhance the perception of the freeciv-server game process:
(return) type | function name/variable | arguments | comments |
Boolean | game_started | (Player player) | Trigger at game started. The `game_started` supports to display the welcome message at the beginning of the game, if you use the `turn_begin` to set turn=1 to display the welcome message, it will not take effect, because the game thinks that it is already in the current turn running state, and will not trigger the judgment of the `turn_begin`, although this function can be achieved by setting the technique of phase=1 additionally, but the setting will cause other players to act first, which will bring unexpected problems. |
Boolean | game_ended | (Player player) | Trigger at game ended. Since freeciv-server has many internal conditions for ending the game, all the end states of the game can be recycled by using game_ended. If game ended, set mini-game `status`=1(MinitaskGameStatus.MGS_END_GAME). |
Boolean | action_finished_worker_build | (City city) | Trigger at activity finished by worker. |
Boolean | action_started_worker_build | (City city) | Trigger at activity started by worker. |
Secondly, calculate the mini-score and mini-goal.
Taking mini-game battle
as an example, the formula for calculating the mini-score
is as follows:
\(\text{mini_score}=\text{unit_cnt_of_human_player} - \text{unit_cnt_of_ai_player}\)
The larger the mini_score is, the more units of human player survives, the better, and the more units of ai player is destroyed, the better. The mini-goal
is setting to
\(\text{mini_goal}=\text{unit_cnt_of_human_player}\)
It means that if you want to satisfy mini_score>=mini_goal to succeed, you need to destroy all units of ai player.
Finally, wrap your message of mini-game and send it out throught E.SCRIPT event. The event function is:
Large batch auto random generation
The auto random generation is supported by the civrealm-sav
module. To implement a new mini-game dependently, you should inherit class SavTaskGenerator
. For example,
from freeciv_sav.tasks.sav_task import SavTaskGenerator
class NewMiniGameGenerator(SavTaskGenerator):
def create_new_game(self, lua_conf:str, *args, **kwargs):
"""
Create new game.
Parameters
----------
lua_conf : str
The lua script designed.
"""
while True:
{Call the functions from tools to implement randomization}
break
return
The tools contains map_op
unit_op
, player_op
, game_op
, etc. The main functions of tools are as follows:
OP | function name | comments |
map_op | gen_random_walk_map | Randomly generate mini-game map by random walk with modifying the terrain, resource and shape of land. |
unit_op | set_location_with_cluster | Randomly set location for units. |
player_op | set_name | Assignment the name of mini-game. |
game_op | set_init_status | Set game status initially. |
Use these functions to help you to implement large batch auto random generation of mini-game.
Mini-Game Validation
Check your mini-game inside freeciv-web
, and test the mini-game to follow the section Play mini-game as a random agent
. If the tests pass, congratulations on completing the task for creating new mini-game.