more stastics and fixes

This commit is contained in:
Trilarion 2017-12-13 13:42:35 +01:00
parent 8e0802215e
commit 0f8339ba7a
24 changed files with 122 additions and 72 deletions

View File

@ -4,8 +4,8 @@
198 entries
- **[Action games](games/action/_toc.md)** (1)
- **[Adventure games & Visual novels](games/adventure/_toc.md)** (15)
- **[Game frameworks](games/framework/_toc.md)** (46)
- **[Popular required libraries](games/library/_toc.md)** (23)
- **[Game frameworks](games/framework/_toc.md)** (47)
- **[Popular required libraries](games/library/_toc.md)** (22)
- **[Role Playing Games](games/rpg/_toc.md)** (61)
- **[Simulation games](games/simulation/_toc.md)** (10)
- **[Strategy games](games/strategy/_toc.md)** (41)

View File

@ -1,9 +1,9 @@
# Adventure games & Visual novels
[comment]: # (start of autogenerated content, do not edit)
- **[AdaVenture](adaventure.md)** (Ada, stable)
- **[AdaVenture](adaventure.md)** (Ada, mature)
- **[Camelia Girls](camelia_girls.md)** (Ren'py)
- **[Clou!](clou.md)** (C, alpha)
- **[Clou!](clou.md)** (C, beta)
- **[Colossal Cave Adventure](colossal_cave.md)** (Python, mature)
- **[Digital: A Love Story](digital.md)** (Ren'py)
- **[Dragon History](dragon_history.md)** (mature)

View File

@ -4,7 +4,7 @@ _A point & click quest set in ancient Persia._
- Home: https://github.com/fastrgv/AdaVenture
- Download: https://github.com/fastrgv/AdaVenture/releases
- State: stable
- State: mature
- Keywords: point&click, kid-friendly
- Code: see home
- Language(s): Ada

View File

@ -5,7 +5,7 @@ _Remake of the 1986 game They Stole a Million._
- Home: https://sourceforge.net/projects/cosp/
- Media: https://en.wikipedia.org/wiki/The_Clue!
- Download: https://sourceforge.net/projects/cosp/files/
- State: alpha
- State: beta
- Keywords: action/adventure
- Code: https://sourceforge.net/p/cosp/code/ (cvs) https://github.com/vcosta/derclou
- Language(s): C

View File

@ -1,6 +1,7 @@
# Game frameworks
[comment]: # (start of autogenerated content, do not edit)
- **[Allegro](allegro.md)** (C, mature)
- **[Annchienta](annchienta.md)** (C++, mature, inactive since 2009)
- **[Arianne / Marauroa](arianne.md)** (Java, mature)
- **[Blender game engine](blender_game_engine.md)** (C++, mature)
@ -19,14 +20,14 @@
- **[Lumix Engine](lumix.md)** (C++, beta)
- **[LÖVE](loeve.md)** (C++, mature)
- **[Mana](manasource.md)** (C++, beta)
- **[Maratis](maratis.md)** (C++, experimental (4.x))
- **[Maratis](maratis.md)** (C++, beta)
- **[MonoGame](monogame.md)** (C#, mature)
- **[O.H.R.RPG.C.E](ohrrpgce.md)** (Basic, mature)
- **[OGRE3D](ogre3d.md)** (C++, mature)
- **[Octaforge](octaforge.md)** (C++, mature)
- **[Open RPG Maker](openrpgmaker.md)** (alpha, inactive since 2014)
- **[Open RPG Maker](openrpgmaker.md)** (beta, inactive since 2014)
- **[OpenFL](openfl.md)** (Haxe, mature)
- **[OpenRPG](openrpg.md)** (Java, Python, inactive since 2013)
- **[OpenRPG](openrpg.md)** (Java, Python, mature, inactive since 2013)
- **[Orx](orx.md)** (C, mature)
- **[Panda 3D](panda3d.md)** (C++, C, mature)
- **[Polycode](polycode.md)** (C, C++, beta)

View File

@ -4,11 +4,13 @@ _Maratis is a simple cross-platform 3d engine and visual game development tool._
- Home: http://www.maratis3d.org/
- Download: http://www.maratis3d.org/?page_id=57
- State: experimental (4.x)
- State: beta
- Code: https://github.com/anael-seghezzi/Maratis-4 https://code.google.com/archive/p/maratis/source
- Language(s): C++
- Code license: GPL-2.0
Maratis 3.x is mature.
## Building
Maratis 4 uses CMake

View File

@ -4,7 +4,7 @@ _OpenRPG is an Internet application that allows people to play Role Playing Game
- Home: http://www.rpgobjects.com/index.php?c=orpg https://app.assembla.com/spaces/openrpg/wiki/Home
- Download: http://www.rpgobjects.com/index.php?c=orpg&m=getorpg
- State: inactive since 2013
- State: mature, inactive since 2013
- Code: https://sourceforge.net/p/openrpg/svn/HEAD/tree/ (svn)
- Language(s): Java, Python

View File

@ -4,7 +4,7 @@ _Open RPG Maker is a free and open source 2D RPG creation utility, similar to th
- Home: http://openrpgmaker.sourceforge.net/
- Download: https://sourceforge.net/projects/openrpgmaker/files/
- State: alpha, inactive since 2014
- State: beta, inactive since 2014
- Code: see download
## Building

View File

@ -1,7 +1,6 @@
# Popular required libraries
[comment]: # (start of autogenerated content, do not edit)
- **[Allegro](allegro.md)** (C, mature)
- **[Boost (C++ Libraries)](boost.md)** (C++, mature)
- **[Crypto++](crypto.md)** (C++)
- **[Doxygen](doxygen.md)** (C++, mature)

View File

@ -4,11 +4,8 @@
This script runs with Python 3, it could also with Python 2 with some minor tweaks probably, but that's not important.
TODO print all games without license or code information
TODO get number of games with github or bitbucket repository and list those who have neither
TODO list those with exotic licenses (not GPL, zlib, MIT, BSD) or without licenses
TODO Which C, C++ projects do not use CMake
TODO list those inactive (sort by year backwards)
TODO for those games with github repositories get activity, number of open issues, number of merge requests and display in a health monitor file
"""
@ -306,6 +303,22 @@ def parse_entry(content):
info = {}
# state
regex = re.compile(r"- State: (.*)")
matches = regex.findall(content)
if matches:
states = matches[0].split(',')
states = [x.strip() for x in states]
if 'beta' in states:
info['state'] = 'beta'
elif 'mature' in states:
info['state'] = 'mature'
else:
print('Neither beta nor mature in state tag: {}'.format(content))
inactive = next((int(x[14:]) for x in states if x.startswith('inactive since')), None) # only the year
if inactive:
info['inactive'] = inactive
# language
regex = re.compile(r"- Language\(s\): (.*)")
matches = regex.findall(content)
@ -345,20 +358,39 @@ def generate_statistics():
content = f.read()
info = parse_entry(content)
info['file'] = os.path.basename(entry_path)
info['file'] = os.path.basename(entry_path)[:-3] # [:-3] to cut off the .md
infos.append(info)
# total number
number_entries = len(infos)
rel = lambda x: x / number_entries * 100 # converion to percent
statistics += 'analyzed {} entries on {}\n\n'.format(number_entries, datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
# State (beta, mature, inactive)
statistics += '## State\n\n'
number_state_beta = sum(1 for x in infos if 'state' in x and x['state'] == 'beta')
number_state_mature = sum(1 for x in infos if 'state' in x and x['state'] == 'mature')
number_inactive = sum(1 for x in infos if 'inactive' in x)
statistics += '- mature: {} ({:.1f}%)\n- beta: {} ({:.1f}%)\n- inactive: {} ({:.1f}%)\n\n'.format(number_state_mature, rel(number_state_mature), number_state_beta, rel(number_state_beta), number_inactive, rel(number_inactive))
if number_inactive > 0:
entries_inactive = [(x['file'], x['inactive']) for x in infos if 'inactive' in x]
entries_inactive.sort(key=lambda x: -x[1]) # sort by inactive year (more recently first)
entries_inactive = ['{} ({})'.format(*x) for x in entries_inactive]
statistics += '##### Inactive State\n\n' + ', '.join(entries_inactive) + '\n\n'
entries_no_state = [x['file'] for x in infos if 'state' not in x]
if entries_no_state:
entries_no_state.sort()
statistics += '##### Without state tag ({})\n\n'.format(len(entries_no_state)) + ', '.join(entries_no_state) + '\n\n'
# Language
statistics += '## Languages\n\n'
number_no_language = sum(1 for x in infos if 'language' not in x)
if number_no_language > 0:
statistics += 'Without language tag: {} ({:.1f}%)\n\n'.format(number_no_language, number_no_language / number_entries * 100)
entries_no_language = [x['file'][:-3] for x in infos if 'language' not in x] # [:-3] to cut off the .md
statistics += 'Without language tag: {} ({:.1f}%)\n\n'.format(number_no_language, rel(number_no_language))
entries_no_language = [x['file'] for x in infos if 'language' not in x]
entries_no_language.sort()
statistics += ', '.join(entries_no_language) + '\n\n'
@ -372,14 +404,14 @@ def generate_statistics():
unique_languages = [(l, languages.count(l) / len(languages)) for l in unique_languages]
unique_languages.sort(key=lambda x: -x[1])
unique_languages = ['- {} ({:.1f}%)\n'.format(x[0], x[1]*100) for x in unique_languages]
statistics += 'Used languages:\n' + ''.join(unique_languages) + '\n'
statistics += '##### Language frequency\n\n' + ''.join(unique_languages) + '\n'
# Licenses
statistics += '## Code licenses\n\n'
number_no_license = sum(1 for x in infos if 'license' not in x)
if number_no_license > 0:
statistics += 'Without license tag: {} ({:.1f}%)\n\n'.format(number_no_license, number_no_license / number_entries * 100)
entries_no_license = [x['file'][:-3] for x in infos if 'license' not in x] # [:-3] to cut off the .md
statistics += 'Without license tag: {} ({:.1f}%)\n\n'.format(number_no_license, rel(number_no_license))
entries_no_license = [x['file'] for x in infos if 'license' not in x]
entries_no_license.sort()
statistics += ', '.join(entries_no_license) + '\n\n'
@ -393,7 +425,7 @@ def generate_statistics():
unique_licenses = [(l, licenses.count(l) / len(licenses)) for l in unique_licenses]
unique_licenses.sort(key=lambda x: -x[1])
unique_licenses = ['- {} ({:.1f}%)\n'.format(x[0], x[1]*100) for x in unique_licenses]
statistics += 'Used licenses:\n' + ''.join(unique_licenses) + '\n'
statistics += '##### Licenses frequency\n\n' + ''.join(unique_licenses) + '\n'
with open(statistics_path, 'w') as f:
f.write(statistics)

View File

@ -6,13 +6,13 @@
- **[Arx Libertatis](arx_libertatis.md)** (C++, mature)
- **[Atrinik](atrinik.md)** (C)
- **[Blades of Exile](blades_of_exile.md)** (C++, mature)
- **[BrowserQuest](browserquest.md)** (Javascript, matures)
- **[BrowserQuest](browserquest.md)** (Javascript, mature)
- **[Catch Challenger](catch_challenger.md)** (C++)
- **[Choria](choria.md)** (C++, C)
- **[Crossfire](crossfire.md)** (C, Java)
- **[DNT](dnt.md)** (C++, beta, inactive since 2016)
- **[Daimonin](daimonin.md)** (C, mature)
- **[Dark City](dark_city.md)** (PHP, inactive since 2012)
- **[Dark City](dark_city.md)** (PHP, mature, inactive since 2012)
- **[Dawn](dawn.md)** (C++, beta, inactive since 2011)
- **[Deliantra](deliantra.md)** (C, mature)
- **[Dragon Hunt](dragon_hunt.md)** (Python, GPL-2.0, mature)
@ -26,9 +26,9 @@
- **[Freedink](freedink.md)** (C++)
- **[FreedroidRPG](freedroid.md)** (C, mature)
- **[Gee Whiz](geewhiz.md)** (C, GPL-2.0, beta, inactive since 2004)
- **[Goblin Hack](goblin_hack.md)** (C++, beta, inactive since )
- **[Goblin Hack](goblin_hack.md)** (C++, beta, inactive since 2009)
- **[Hale](hale.md)** (Java, beta, inactive since 2014)
- **[Hero of Allacrost](allacrost.md)** (C++, Lua, stable)
- **[Hero of Allacrost](allacrost.md)** (C++, Lua, mature)
- **[Ilarion](ilarion.md)** (C++, Java, Lua, mature)
- **[Imperium](imperium.md)** (mature)
- **[KQ Lives](kq_lives.md)** (C, GPL-2.0, beta, inactive since 2011)
@ -58,7 +58,7 @@
- **[Valyria Tear](valyria_tear.md)** (Lua, C++, C)
- **[VegaTrek](vegatrek.md)** (beta, inactive since 2013)
- **[Waste's Edge](wastes_edge.md)** (Python, GPL-2.0, beta)
- **[World of Phaos](world_of_phaos.md)** (PHP, inactive since 2011)
- **[World of Phaos](world_of_phaos.md)** (PHP, mature, inactive since 2011)
- **[XU4](xu4.md)** (C++, mature)
- **[Zelda: Mystery of Solarus DX](zelda_mystery_of_solarus_dx.md)** (Lua)
- **[diablo-js](diablo_js.md)** (Java, Javascript, mature)

View File

@ -4,7 +4,7 @@ _Hero of Allacrost is a 2D role-playing game inspired by classic console RPGs._
- Home: http://allacrost.org
- Download: https://bitbucket.org/allacrost/allacrost/downloads/
- State: stable
- State: mature
- Keywords: SP, 2D
- Code: https://bitbucket.org/allacrost/allacrost/src (hg)
- Language(s): C++, Lua

View File

@ -4,7 +4,7 @@ _A Massively Multiplayer Adventure._
- Home: http://browserquest.mozilla.org/
- Media: https://en.wikipedia.org/wiki/BrowserQuest
- State: matures
- State: mature
- Keywords: MMORPG
- Code: https://github.com/mozilla/BrowserQuest
- Language(s): Javascript

View File

@ -4,7 +4,7 @@ _DarkCity is a MMORPG game, in text mode on the Internet._
- Home: https://sourceforge.net/projects/darkcity/
- Download: https://sourceforge.net/projects/darkcity/files/
- State: inactive since 2012
- State: mature, inactive since 2012
- Code: https://sourceforge.net/p/darkcity/code/HEAD/tree/ (svn)
- Language(s): PHP
- Code license: GPL-2.0

View File

@ -4,7 +4,7 @@ _A roguelike opengl-based smooth-scrolling ASCII graphics game._
- Home: https://sourceforge.net/projects/goblinhack/
- Download: https://sourceforge.net/projects/goblinhack/files/
- State: beta, inactive since
- State: beta, inactive since 2009
- Keywords: Sp, roguelike
- Code: https://github.com/goblinhack/goblinhack https://sourceforge.net/p/goblinhack/code/HEAD/tree/ (svn)
- Language(s): C++

View File

@ -4,7 +4,7 @@ _Online Roleplaying Game browser based, which takes place in the high fantasy wo
- Home: http://worldofphaos.com/index.php?site=online_rpg https://sourceforge.net/projects/phaosrpg/
- Download: https://sourceforge.net/projects/phaosrpg/files/
- State: inactive since 2011
- State: mature, inactive since 2011
- Code: see download
- Language(s): PHP
- Code license: GPL-2.0

View File

@ -3,10 +3,10 @@
[comment]: # (start of autogenerated content, do not edit)
- **[3d.city](3d_city.md)** (Javascript)
- **[LinCity](lincity.md)** (C, mature, inactice since 2005)
- **[LinCity-NG](lincity_ng.md)** (C++, alpha)
- **[LinCity-NG](lincity_ng.md)** (C++, beta)
- **[Micropolis](micropolis.md)** (C++, Java, Python, mature)
- **[Open Transport Tycoon](open_transport_tycoon.md)** (C++, mature)
- **[OpenCity](open_city.md)** (C++, alpha)
- **[OpenCity](open_city.md)** (C++, beta)
- **[Our Personal Space](our_personal_space.md)** (Ren'py)
- **[Pioneer](pioneer.md)** (C++, C, mature)
- **[SimuTrans](simutrans.md)** (C++, mature)

View File

@ -4,7 +4,7 @@ _City simulation game._
- Home: https://sourceforge.net/projects/lincity-ng.berlios/
- Download: https://sourceforge.net/projects/lincity-ng.berlios/files/
- State: alpha
- State: beta
- Code: see download
- Language(s): C++
- Code license: GPL

View File

@ -4,7 +4,7 @@ _Another 3D city simulator._
- Home: http://www.opencity.info/
- Download: http://www.opencity.info/en/Download.html
- State: alpha
- State: beta
- Code: http://svn.code.sf.net/p/opencity/code/trunk/opencity/ (svn)
- Language(s): C++
- Code license: GPL-2.0

View File

@ -1,7 +1,21 @@
[comment]: # (autogenerated content, do not edit)
# Statistics
analyzed 198 entries on 2017-12-12 11:13:31
analyzed 198 entries on 2017-12-13 13:41:30
## State
- mature: 103 (52.0%)
- beta: 49 (24.7%)
- inactive: 35 (17.7%)
##### Inactive State
dnt (2016), egoboo (2015), roguish (2015), sintel (2014), openrpgmaker (2014), rpge (2014), argentum_online (2014), hale (2014), lips_of_suna (2014), open_tibia (2014), summoming_wars (2014), openrpg (2013), trinity_reign (2013), vegatrek (2013), c_evo (2013), dark_city (2012), parpg (2012), dawn (2011), kobolds_quest_2 (2011), kq_lives (2011), project_diaspora (2011), world_of_phaos (2011), star_control_2 (2011), radakan (2010), singularity (2010), annchienta (2009), fall_of_imiryn (2009), goblin_hack (2009), glest (2009), silvertree (2007), crown_and_cutless (2006), geewhiz (2004), openglad (2004), civil (2003), umbra (2002)
##### Without state tag (46)
3d_city, atrinik, birth_of_the_empires, camelia_girls, catch_challenger, choria, crimson_fields, crossfire, crypto, dash, deltaengine, digital, dungeon_monkey_eternal, easyrpgplayer, evol_online, flare_engine, freedink, gigalomania, land_of_fire, manaworld, maxr, meritous, micropolis_js, mkxp, murder_in_the_public_domain, open_general, openal, openalsoft, other_life, our_personal_space, room_for_change, sandboxgamemaker, sentient_storage, source_of_tales, star_maiden_rio, superpowers, tanks_of_freedom, twin_engine, ufo2000, valyria_tear, visions_from_the_other_side, warzone_2100, xoreos, yaml_cpp, zelda_mystery_of_solarus_dx, zero_k
## Languages
@ -9,32 +23,33 @@ Without language tag: 16 (8.1%)
crimson_fields, dragon_history, evol_online, imperium, land_of_fire, meritous, murder_in_the_public_domain, open_general, openal, openrpgmaker, parpg, solaris, space_station_13, star_maiden_rio, vegatrek, xconq
Used languages:
##### Language frequency
- C++ (40.3%)
- C (24.3%)
- Python (8.4%)
- Java (8.4%)
- Python (8.4%)
- Lua (4.4%)
- Javascript (2.2%)
- Ren'py (1.8%)
- PHP (1.3%)
- C# (1.3%)
- PHP (1.3%)
- Haxe (0.9%)
- Angelscript (0.4%)
- GDScript (0.4%)
- D (0.4%)
- VB (0.4%)
- Text (0.4%)
- Ada (0.4%)
- Objective C (0.4%)
- Typescript (0.4%)
- Kotlin (0.4%)
- Basic (0.4%)
- Delphi (0.4%)
- Pascal (0.4%)
- Delphi Pascal (0.4%)
- Clojure (0.4%)
- D (0.4%)
- Typescript (0.4%)
- Angelscript (0.4%)
- ActionScript (0.4%)
- Text (0.4%)
- Objective C (0.4%)
- VB (0.4%)
- Pascal (0.4%)
- Basic (0.4%)
- Ada (0.4%)
- Clojure (0.4%)
- Kotlin (0.4%)
- GDScript (0.4%)
- Delphi Pascal (0.4%)
## Code licenses
@ -42,7 +57,8 @@ Without license tag: 28 (14.1%)
atrinik, camelia_girls, catch_challenger, clou, crimson_fields, digital, dragon_hunt, evol_online, freerails, geewhiz, heroes_of_wesnoth, imperium, kobolds_quest_2, kq_lives, land_of_fire, meritous, open_general, openglad, openrpg, openrpgmaker, other_life, parpg, sintel, solaris, space_station_13, star_maiden_rio, warzone_2100, wastes_edge
Used licenses:
##### Licenses frequency
- GPL-2.0 (37.1%)
- GPL-3.0 (18.8%)
- MIT (12.9%)
@ -52,21 +68,21 @@ Used licenses:
- Apache-2.0 (2.4%)
- BSD-3 (1.8%)
- LGPL-2.0 (1.2%)
- Mixed (1.2%)
- LGPL-2.1 (1.2%)
- Freeware (0.6%)
- AGPL-3.0 (0.6%)
- zlib (core) (0.6%)
- Different, see file Copying, liblzma is public domain (0.6%)
- Ms-MPL MIT (0.6%)
- Proprietary (0.6%)
- GPl-3.0 (0.6%)
- Mixed (1.2%)
- BSD (0.6%)
- Artistic License (0.6%)
- None found (0.6%)
- Freeware (0.6%)
- Boost-1.0 (0.6%)
- LGPL-3.0 (0.6%)
- Public Domain (0.6%)
- GPl-3.0 (0.6%)
- zlib (core) (0.6%)
- None found (0.6%)
- Different, see file Copying, liblzma is public domain (0.6%)
- Proprietary (0.6%)
- ISC (0.6%)
- Public Domain (0.6%)
- MPL-2.0 (0.6%)
- BSD (0.6%)
- Ms-MPL MIT (0.6%)
- AGPL-3.0 (0.6%)

View File

@ -5,7 +5,7 @@ _0 A.D. is a free, open-source, cross-platform real-time strategy game._
- Home: https://play0ad.com/
- Media: <https://en.wikipedia.org/wiki/0_A.D._(video_game)>
- Download: https://play0ad.com/download/
- State: alpha
- State: beta
- Keywords: RTS
- Code: https://svn.wildfiregames.com/public/ps/trunk/ (svn)
- Language(s): C++

View File

@ -1,7 +1,7 @@
# Strategy games
[comment]: # (start of autogenerated content, do not edit)
- **[0AD](0ad.md)** (C++, alpha)
- **[0AD](0ad.md)** (C++, beta)
- **[Advanced Strategic Command](asc.md)** (C++, mature)
- **[Battle for Wesnoth](wesnoth.md)** (C++, mature)
- **[Birth of the Empires](birth_of_the_empires.md)** (C++)
@ -12,7 +12,7 @@
- **[Endgame: Singularity](singularity.md)** (Python, beta, inactive since 2010)
- **[Free Orion](freeorion.md)** (C++, Python, beta)
- **[FreeCol](freecol.md)** (Java, mature)
- **[FreeRails](freerails.md)** (Java, alpha)
- **[FreeRails](freerails.md)** (Java, beta)
- **[Freeciv](freeciv.md)** (C, mature)
- **[Freeciv WebGL](freeciv_web.md)** (Javascript, Java, mature)
- **[Gigalomania](gigalomania.md)** (C++)
@ -20,7 +20,7 @@
- **[Globulation2](globulation2.md)** (C++, mature)
- **[Heroes of Wesnoth](heroes_of_wesnoth.md)** (C++, beta)
- **[LGeneral](lgeneral.md)** (C, mature)
- **[LordsAWar!](lordsawar.md)** (C++, stable)
- **[LordsAWar!](lordsawar.md)** (C++, mature)
- **[Mechanized Assault & eXploration Reloaded ](maxr.md)** (C++, C)
- **[MegaGlest](megaglest.md)** (C++, mature)
- **[Megamek](megamek.md)** (Java, mature)

View File

@ -4,7 +4,7 @@ _Real time MP strategy game where players compete to build the most powerful rai
- Home: http://freerails.sourceforge.net/
- Download: https://sourceforge.net/projects/freerails/files/jfreerails/
- State: alpha
- State: beta
- Keywords: RTS
- Code: https://sourceforge.net/p/freerails/code/ (cvs)
- Language(s): Java

View File

@ -5,7 +5,7 @@ _LordsAWar! is a free, turn-based strategy game where up to 8 players strive for
- Home: http://www.nongnu.org/lordsawar/
- Media: <https://en.wikipedia.org/wiki/Warlords_(game_series)#LordsAWar!>
- Download: see home
- State: stable
- State: mature
- Keywords: TBS
- Code: https://git.savannah.nongnu.org/git/lordsawar.git
- Language(s): C++