#include "world/guests.h" #include "world/cast.h" #include "render/figure.h" #include #include static const char *const WOMEN[] = { "Lena", "Mia", "Hanna", "Sophie", "Lea", "Marie", "Nele", "Clara", "Ida", "Frieda", "Paula", "Greta", "Emma", "Luisa", "Merle", "Ronja", "Alma", "Jule" }; static const char *const MEN[] = { "Jonas", "Felix", "Paul", "Ben", "Lukas", "Moritz", "Finn", "Emil", "Theo", "Anton", "Jakob", "Niklas", "Ole", "Malte", "Hannes", "Bruno", "Leon", "Max" }; #define COUNTOF(a) ((int)(sizeof(a) / sizeof((a)[0]))) static unsigned mix(unsigned h) { h ^= h >> 16; h *= 0x7feb352du; h ^= h >> 15; h *= 0x846ca68bu; h ^= h >> 16; return h; } /* 0..1, the same for the same guest and question */ static float dice(int k, unsigned q) { return (float)(mix((unsigned)k * 7919u + q * 104729u) & 0xffffu) / 65535.0f; } static Vec3 pick(const Vec3 *from, int n, float d) { return from[(int)(d * (float)n) % n]; } static const Vec3 SKINS[] = { { 0.96f, 0.80f, 0.68f }, { 0.92f, 0.74f, 0.60f }, { 0.86f, 0.66f, 0.50f }, { 0.72f, 0.52f, 0.38f }, { 0.56f, 0.38f, 0.26f }, { 0.40f, 0.27f, 0.19f } }; static const Vec3 HAIRS[] = { { 0.12f, 0.10f, 0.10f }, { 0.30f, 0.19f, 0.12f }, { 0.55f, 0.38f, 0.22f }, { 0.80f, 0.66f, 0.40f }, { 0.70f, 0.30f, 0.16f }, { 0.20f, 0.45f, 0.55f }, { 0.75f, 0.35f, 0.60f } }; static const Vec3 SHIRTS[] = { { 0.88f, 0.86f, 0.80f }, { 0.12f, 0.12f, 0.14f }, { 0.86f, 0.30f, 0.30f }, { 0.25f, 0.45f, 0.75f }, { 0.95f, 0.70f, 0.20f }, { 0.40f, 0.65f, 0.40f }, { 0.65f, 0.40f, 0.75f }, { 0.95f, 0.55f, 0.65f }, { 0.20f, 0.70f, 0.70f } }; static const Vec3 PANTS[] = { { 0.22f, 0.26f, 0.40f }, { 0.15f, 0.15f, 0.16f }, { 0.50f, 0.44f, 0.34f }, { 0.35f, 0.38f, 0.30f }, { 0.60f, 0.25f, 0.30f }, { 0.75f, 0.72f, 0.65f } }; int Guest_mate(int k) { return k % 2 ? k + 1 : k - 1; } Object *Guest_create(int k, Vec3 at) { bool female = dice(k, 1) < 0.5f; float kg = female ? 55.0f + 20.0f * dice(k, 2) : 68.0f + 25.0f * dice(k, 2); Object *o = Object_create(OBJ_HUMAN, PALETTE_MODERN, at, vec3(0.5f, 1.75f, 0.25f), kg); if (!o) return NULL; o->guest = k; o->supporter = ((k - 1) / 2) % 4 == 0; /* (one pair in four: a free ticket for 2 x 6 h of work) */ char name[32]; snprintf(name, sizeof name, "%s", female ? WOMEN[(int)(dice(k, 3) * COUNTOF(WOMEN)) % COUNTOF(WOMEN)] : MEN[(int)(dice(k, 3) * COUNTOF(MEN)) % COUNTOF(MEN)]); Object_setPerson(o, name, dice(k, 4) < 0.12f ? HAND_LEFT : HAND_RIGHT); FigureLook worn = Figure_wardrobe(5 + k); o->look = worn; o->look.skin = pick(SKINS, COUNTOF(SKINS), dice(k, 5)); o->look.hair = pick(HAIRS, COUNTOF(HAIRS), dice(k, 6) * (dice(k, 7) < 0.8f ? 0.57f : 1.0f)); /* (mostly natural) */ o->look.shirt = pick(SHIRTS, COUNTOF(SHIRTS), dice(k, 8)); o->look.pants = pick(PANTS, COUNTOF(PANTS), dice(k, 9)); o->look.shoes = vec3(0.2f + 0.6f * dice(k, 10), 0.18f + 0.5f * dice(k, 10), 0.16f + 0.4f * dice(k, 11)); o->look.height = female ? 1.58f + 0.17f * dice(k, 12) : 1.70f + 0.18f * dice(k, 12); o->look.hair_style = female ? (dice(k, 13) < 0.8f ? HAIR_LONG : HAIR_SHORT) : (dice(k, 13) < 0.2f ? HAIR_LONG : HAIR_SHORT); o->look.long_sleeves = dice(k, 14) < 0.3f; float g = dice(k, 15); o->look.garment = female ? (g < 0.3f ? GARMENT_SKIRT : g < 0.5f ? GARMENT_DRESS : g < 0.75f ? GARMENT_SHORTS : GARMENT_TROUSERS) : (g < 0.45f ? GARMENT_SHORTS : GARMENT_TROUSERS); o->look.hat = dice(k, 16) < 0.2f ? HAT_CAP : dice(k, 16) < 0.28f ? HAT_BEANIE : HAT_NONE; o->look.hat_color = pick(SHIRTS, COUNTOF(SHIRTS), dice(k, 17)); o->female = female; o->urinella = false; o->urinellas = 0; o->temperament.pride = dice(k, 18) - 0.5f; o->temperament.energy = 0.2f + 0.7f * dice(k, 19); /* (festival people: lively) */ o->temperament.nerves = 0.6f * dice(k, 20) - 0.3f; o->tolerance = 0.7f + 0.6f * dice(k, 21); o->fitness = 0.3f + 0.6f * dice(k, 22); o->wits = 0.4f + 0.4f * dice(k, 23); o->height_fear = 0.5f * dice(k, 24); o->smoker = dice(k, 25) < 0.4f ? 0.3f + 0.5f * dice(k, 26) : 0.0f; o->cigarettes = o->smoker > 0.0f ? 6 + (int)(14.0f * dice(k, 27)) : 0; o->lighter = o->smoker > 0.0f; o->craving = 0.3f; o->commitment = 0.0f; o->fun = 0.55f + 0.15f * dice(k, 28); o->like = 0.2f + 0.15f * dice(k, 40); /* (strangers to you) */ o->love = 0.1f * dice(k, 41); o->ai.character.willing = 0.2f + 0.3f * dice(k, 29); o->ai.character.tempo = 1.0f; o->ai.character.ponder = 0.5f; o->tempo = 1.0f; for (int q = 0; q < ORDER_COUNT; q++) o->skill[q] = 0.2f + 0.3f * dice(k, 30 + (unsigned)q); Object_setHeight(o, o->look.height); o->pace = 1.0f + 0.12f * o->temperament.energy; return o; } /* Up on the meadow right of the strip of wood, below the lane to the chicken halls: three rows of six. */ Vec3 Guest_campSpot(int k) { int pair = ((k - 1) / 2) % GUEST_SPOTS; int col = pair % 6, row = pair / 6; return vec3(9.0f + 4.0f * (float)col + (row % 2 ? 1.3f : 0.0f), 0.0f, 86.0f + 3.8f * (float)row); } Vec3 Guest_campDoor(void) { return vec3(0.0f, 0.0f, -1.0f); } Vec3 Guest_gate(void) { return vec3(63.0f, 0.0f, 89.5f); }