image

Давным-давно, во времена, когда я не знал практически ничего о программировании, мне пришла в голову мысль о том, как было бы здорово иметь статистику в одной из моих любимых игр — Quake. Прошло время, появились более-менее адекватные знания языков программирования. И я вспомнил о своём намерении.
В этой статье я хочу показать, по-моему мнению, самый простой способ реализации такой задачи на языке C++.

Что мы имеем?


У нас есть файл логов, который называется games.txt и лежит в директории ../QuakeII/baseq3/. В логи пишется важная информация для составления статистики. К примеру, подобранные вещи и убийства.
Логи выглядят следующим образом.
games.txt
0:00 InitGame: \sv_floodProtect\1\sv_maxRate\0\sv_hostname\noname\version\Q3 1.32 win-x86 Oct 7 2002\dmflags\0\fraglimit\20\timelimit\0\g_gametype\0\protocol\68\mapname\Q3TOURNEY1\sv_privateClients\0\sv_maxclients\8\sv_punkbuster\0\sv_minPing\0\sv_maxPing\0\sv_allowDownload\0\g_redTeam\Stroggs\g_blueTeam\Pagans\capturelimit\0\gamename\baseq3\g_maxGameClients\0\g_needpass\0
0:00 ClientConnect: 0
0:00 ClientUserinfoChanged: 0 n\UnnamedPlayer\t\0\model\sarge\hmodel\sarge\g_redteam\\g_blueteam\\c1\4\c2\5\hc\100\w\0\l\0\tt\0\tl\0
0:00 ClientUserinfoChanged: 0 n\UnnamedPlayer\t\0\model\sarge\hmodel\sarge\g_redteam\\g_blueteam\\c1\4\c2\5\hc\100\w\0\l\0\tt\0\tl\0
0:00 ClientBegin: 0
0:08 Item: 0 item_armor_combat
0:08 Item: 0 ammo_rockets
0:09 Item: 0 ammo_shells
0:12 Item: 0 ammo_shells
0:18 Item: 0 ammo_rockets
0:24 Item: 0 ammo_bullets
0:31 Item: 0 weapon_rocketlauncher
0:41 Item: 0 item_health_large
0:48 Item: 0 ammo_rockets
0:48 Item: 0 ammo_bullets
0:50 Item: 0 ammo_rockets
0:50 Item: 0 item_armor_combat
0:52 Item: 0 ammo_shells
0:53 Item: 0 weapon_shotgun
0:55 Item: 0 ammo_shells
0:58 Item: 0 item_regen
1:01 Item: 0 ammo_rockets
1:13 Item: 0 ammo_bullets
1:20 Item: 0 weapon_rocketlauncher
1:42 Item: 0 ammo_rockets
1:42 Item: 0 ammo_bullets
1:43 Item: 0 ammo_shells
1:44 Item: 0 ammo_rockets
1:44 Item: 0 item_armor_combat
1:45 Item: 0 ammo_shells
1:46 Item: 0 weapon_shotgun
1:47 Item: 0 item_health
1:47 Item: 0 item_health_large
1:52 Item: 0 ammo_rockets
2:00 Item: 0 weapon_shotgun
2:07 say: UnnamedPlayer: god
2:17 say: UnnamedPlayer: weapon
2:26 Item: 0 item_regen
2:28 Item: 0 ammo_rockets
2:31 Item: 0 weapon_shotgun
2:32 Item: 0 ammo_shells
2:33 Item: 0 ammo_rockets
2:34 Item: 0 item_armor_combat
2:37 Item: 0 ammo_bullets
2:38 Item: 0 ammo_rockets
3:03 ShutdownGame:

Наша задача на сегодня


Давайте сделаем что-нибудь простое и понятное, для начала. Например, соберём из нашего лога все убийства и подобранные айтемы.

Идём писать код


#include <iostream> // Мы будем выводить текст в консоль
#include <string> // Мы будем пользоваться типом string
#include <fstream> // Мы будем читать файл логов
using namespace std;
int main()
{
	int total_kills = 0;
	int total_items = 0;
	string buffer;
	ifstream logfile("games.txt"); // Открываем файл для работы
    if (!logfile.is_open()) return 0;
	while(1)
	{
		logfile >> buffer; // Читаем до пробела
		if (buffer == "endthis") break; // Ввод заканчивается, когда мы встречаем событие endthis
		if (!buffer.empty() && buffer[buffer.length()-1] == ':') // У каждого события в конце стоит двоеточие, по нему мы и узнаём, что это команда
		{
			if (buffer == "Kill:") // Если считанное является командой
			{
				total_kills++;
			} else
			if (buffer == "Item:")
			{
				total_items++;
			}
		}
	}
	logfile.close(); // Закрываем за собой файл.
	cout << endl << "total kills: " << total_kills << endl;
	cout << endl << "total items: " << total_items << endl;
return 0;
}


Фича Quake


image
Файл логов называется games.txt, или нет? Программа не хотела работать, проблема оказалась, как всегда, не там, где я её пытался найти. Дело в том, что игра называет этот файл как-то по особому, fstream не видел и не открывал. Решил я это простым переименованием файла.

Результат выполнения программы


image

Продолжение следует


В последующих статьях, я буду постепенно усложнять задачу и добавлять новые возможности. При этом буду стараться как можно более понятно объяснить принцип работы.