sw-battle-test-c

Interesting test task in C instead of C++
git clone git://bsandro.tech/sw-battle-test-c
Log | Files | Refs | README

commit abd873fd4c8212343659f4a5879d87e818c7f653
Author: bsandro <email@bsandro.tech>
Date:   Fri, 21 Aug 2026 00:57:24 +0300

init

Diffstat:
A.gitignore | 2++
AMakefile | 30++++++++++++++++++++++++++++++
AREADME.md | 151++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acommands_example.txt | 14++++++++++++++
Acore/map.c | 9+++++++++
Acore/map.h | 6++++++
Acore/world.c | 6++++++
Acore/world.h | 7+++++++
Amain.c | 9+++++++++
9 files changed, 234 insertions(+), 0 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -0,0 +1,2 @@ +*.o +sw-battle-test-c diff --git a/Makefile b/Makefile @@ -0,0 +1,30 @@ +NAME=$(shell basename ${PWD}) +SDL_CFLAGS=$(shell pkg-config --cflags sdl2 SDL2_image) +SDL_LDFLAGS=$(shell pkg-config --libs sdl2 SDL2_image) +SRC:=$(wildcard *.c **/*.c) +DEPS:=$(wildcard *.h **/*.h) +OBJ:=$(SRC:.c=.o) +CFLAGS=-std=c99 -Wpedantic -Wall -Wextra -ffast-math -I. $(SDL_CFLAGS) +ifeq (${DEBUG},1) +CFLAGS+=-O0 -g +else +CFLAGS+=-O3 -mtune=native -march=native +endif +LDFLAGS=-lc -lm -flto $(SDL_LDFLAGS) +#CC=gcc + +all: $(NAME) + +.PHONY: clean + +clean: + rm -f $(OBJ) $(NAME) + +%.o : %.c $(DEPS) + $(CC) $(CFLAGS) -c $< -o $@ + +$(NAME): $(OBJ) + $(CC) $(OBJ) -o $@ $(LDFLAGS) + +run: $(NAME) + ./$(NAME) diff --git a/README.md b/README.md @@ -0,0 +1,150 @@ +# **Цель** + +Цель задания — **продемонстрировать навыки проектирования ПО.** + +- Не беспокойтесь о производительности, использовании потоков или подключении библиотек. +- Мы не ожидаем детерминированного результата работы — это лишь усложнило бы задачу. +- Время выполнения не ограничено, но предполагается, что работа займёт не более 6–8 часов. + +## **Что мы хотим увидеть:** + +1. Понятный и аккуратный код с прозрачной логикой работы. +2. Чёткое разграничение зон ответственности между сущностями проекта. +3. Расширяемую архитектуру, которая позволяет легко добавлять новые сущности и механики взаимодействия + - Представьте, что после вас придут 10 младших разработчиков, которые будут одновременно добавлять новые функции. + - Ознакомьтесь с README.MD в директориях Core и Feature — они помогут лучше понять цели задачи. +4. Заметки в документе KNOWN_ISSUES.md - где вы оставите известные вам недостатки и сомнения по вашему решению, к + примеру из-за нехватки времени. + +# **Задача** + +Создайте пошаговую симуляцию боевых столкновений юнитов на карте для тестирования игровых механик. + +На карте размером W×H клеток можно размещать юнитов. + +- Юниты различаются по типам, **действиям** и **характеристикам**. +- Каждому юниту присвоен уникальный идентификатор **Id** (целое число) +- За один ход каждый юнит может выполнить одно действие. + - Юниты совершают действия в порядке их создания. +- Юнит всегда размещен по каким то координатам на карте. +- Юнит может занимать клетку, не позволяя другим на нее встать. +- Большинство юнитов имеет характеристику **HP** (Health Points). + - При **HP** ≤ 0 юнит выполняет свои действия в текущем ходу и исчезает перед началом следующего. +- Часть юнитов обладает способностью перемещения: + - Они могут переместиться в любую из восьми прилегающих клеток за ход. + - Если цель недостижима за один ход, они продолжают движение к ней в последующих ходах. + - Статичные юниты должны оставаться неподвижными при любых условиях. + +Симуляция заканчивается, когда нет юнитов, способных действовать в следующем ходу, или на карте остается только один +юнит. + +## Юниты, которых нужно реализовать: + +### Мечник + +- **Характеристики:** HP, Strength +- Действия + - **Сокрушающий удар:** Бьет одного случайного юнита в соседней клетке, нанося ему **Strength** единиц урона. + - Если некого бить, перемещается. + +### Охотник + +- **Характеристики:** HP, Agility, Strength, Range +- Действия + - **Стремительный выстрел:** Стреляет в случайного юнита на расстоянии от 2 до **Range** клеток, нанося ему + **Agility** единиц урона. Может стрелять только если в соседних клетках нет других юнитов. + - **Удар из тени:** Если стрелять не может, бьет одного случайного юнита в соседней клетке, нанося ему **Strength** + единиц урона. + - Если некого бить, перемещается. + +# Приложение + +При запуске приложение получает путь к файлу со сценарием симуляции, где описаны **команды** для создания карты и +юнитов, а также перемещения юнитов по карте. Приложение должно выводить все происходящие события в **stdout**. + +Так как на карте нет препятствий, сложные алгоритмы поиска пути не требуются. + +## Команды + +- `CREATE_MAP W H` — Создает карту размером `W`×`H`. Эта команда начинает любой сценарий. +- `SPAWN_SWORDSMAN I X Y H S` — Создает мечника с идентификатором `I` в точке `X`,`Y` с характеристиками здоровья `H` и + силы `S`. +- `SPAWN_HUNTER I X Y H A S R` — Создает охотника с идентификатором `I` в точке `X`,`Y` с характеристиками здоровья `H`, + ловкости `A`, силы `S` и дальности `R`. +- `MARCH I X Y` — Приказывает юниту `I` переместиться в точку `X`,`Y`. + +## События + +- `MAP_CREATED` — Создание карты. +- `MARCH_STARTED`, `MARCH_ENDED` — Начало и конец перемещения юнита. +- `UNIT_SPAWNED`, `UNIT_DIED` — Создание и смерть юнита. +- `UNIT_MOVED` — Перемещение юнита на клетку. +- `UNIT_ATTACKED` — Атака одного юнита на другого. + +Код парсера команд и вывода событий в лог уже содержится в проекте. Если необходимо, его можно менять. Формат ввода и +вывода менять нельзя. + +Пример сценария находится в файле _commands_example.txt_. Пример лога событий находится в файле _main.cpp_. + +# Ограничения + +- Не подключать внешние 3rd-party зависимости, только стандартная библиотека +- Вы можете поменять проект как угодно для достижения цели, даже не используя предоставленную структуру и код + - это не является ни плюсом ни минусом, мы предоставили структуру и код, желая упростить задачу, сэкономить вам + время. + +# Технические требования + +- **ОС:** Ubuntu +- **Компилятор:** clang 15+ +- **Стандарт:** C++17 или новее +- **Система сборки:** cmake (в проекте должен быть CMakeLists.txt) +- Задание необходимо опубликовать в любом публичном гит-репозитории (GitHub, Bitbucket и т.д.). + +_В процессе выполнения задания вы можете присылать любые вопросы._ + +# Планы на расширения + +При проектировании учитывайте планы по добавлению новых юнитов, действий и характеристик. + +Возможность создания таких Юнитов с таким поведением не трогая код в Core является важным критерием. + +Эту функциональность не нужно реализовывать в коде, это подсказка для расширяемости. + +## Башня + +- **Характеристики:** HP, Power +- Действия + - **Прицельный выстрел:** Стреляет в случайного юнита на расстоянии от 2 до 5 клеток, нанося ему **Power** единиц + урона. + - Не может перемещаться. + +## Лекарь + +- **Характеристики:** HP, Spirit +- Действия + - **Малое исцеление:** Восстанавливает **Spirit** единиц здоровья одному случайному юниту в радиусе 2 клеток. + - Если некого лечить, перемещается. + +## Ворон + +- **Характеристики:** HP, Agility +- **Летающий юнит:** + - Не занимает клетку на карте. + - Может перемещаться на 2 клетки за ход. + - Не может быть атакован ближнем боем. + - Может быть атакован в дальнем бою, минимальная и максимальная дистанция атаки "стрелка" на ворона снижена на 1. +- Действия + - **Удар когтем:** Бьет одного случайного юнита в соседних клетках, нанося ему **Agility** единиц урона. + - Если некого бить, перемещается. + +## Мина + +- **Характеристики:** Power +- Не может быть атакована. +- Не занимает клетку на карте. +- Действия + - Если в радиусе 2х клеток есть юнит - взрывается в следующем ходу, нанося всем юнитам в радиусе 3х клеток **Power** + единиц урона. + - После взрыва исчезает. + - Не может перемещаться. +\ No newline at end of file diff --git a/commands_example.txt b/commands_example.txt @@ -0,0 +1,14 @@ +CREATE_MAP 10 10 + +SPAWN_SWORDSMAN 1 0 0 5 2 + +SPAWN_HUNTER 2 9 0 10 5 1 4 + +MARCH 1 9 0 + +MARCH 2 0 0 + +SPAWN_SWORDSMAN 3 0 9 10 2 + +MARCH 3 0 0 + diff --git a/core/map.c b/core/map.c @@ -0,0 +1,9 @@ +#include <stdlib.h> +#include "map.h" + +//todo: return 1 or 0 +void Map_init(Map *m, int w, int h) { + m->w = w; + m->h = h; +} + diff --git a/core/map.h b/core/map.h @@ -0,0 +1,6 @@ +typedef struct Map { + int w; + int h; +} Map; + +void Map_init(Map *m, int w, int h); diff --git a/core/world.c b/core/world.c @@ -0,0 +1,6 @@ +#include <stddef.h> +#include "world.h" + +World * World_init() { + return NULL; +} diff --git a/core/world.h b/core/world.h @@ -0,0 +1,7 @@ +#include "map.h" + +typedef struct World { + Map map; +} World; + +World * World_init(); diff --git a/main.c b/main.c @@ -0,0 +1,9 @@ +#include <stdio.h> +#include "core/world.h" + +int main(void) { + World w; + Map_init(&w.map, 3, 4); + puts("ok"); + return 0; +}