
Давным-давно, во времена, когда я не знал практически ничего о программировании, мне пришла в голову мысль о том, как было бы здорово иметь статистику в одной из моих любимых игр — 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:
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
Файл логов называется games.txt, или нет? Программа не хотела работать, проблема оказалась, как всегда, не там, где я её пытался найти. Дело в том, что игра называет этот файл как-то по особому, fstream не видел и не открывал. Решил я это простым переименованием файла.
Результат выполнения программы
Продолжение следует
В последующих статьях, я буду постепенно усложнять задачу и добавлять новые возможности. При этом буду стараться как можно более понятно объяснить принцип работы.