Skip to content

Commit

Permalink
Gilgamesh quiz easter egg #712
Browse files Browse the repository at this point in the history
  • Loading branch information
cxong committed Nov 23, 2024
1 parent 5c76e29 commit b26a146
Show file tree
Hide file tree
Showing 11 changed files with 196 additions and 86 deletions.
78 changes: 46 additions & 32 deletions src/cdogs/cwolfmap/cwolfmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -167,38 +167,7 @@ int CWLoad(CWolfMap *map, const char *path, const int spearMission)
CWLevelN3DLoadDescription(languageBuf, i);
}

for (int q = 1;; q++)
{
char *question = CWLevelN3DLoadQuizQuestion(languageBuf, q);
if (question == NULL)
{
break;
}
map->nQuizzes++;
map->quizzes =
realloc(map->quizzes, map->nQuizzes * sizeof(CWN3DQuiz));
CWN3DQuiz *quiz = &map->quizzes[map->nQuizzes - 1];
memset(quiz, 0, sizeof *quiz);
quiz->question = question;
for (char a = 'A';; a++)
{
bool correct = false;
char *answer =
CWLevelN3DLoadQuizAnswer(languageBuf, q, a, &correct);
if (answer == NULL)
{
break;
}
quiz->nAnswers++;
quiz->answers =
realloc(quiz->answers, quiz->nAnswers * sizeof(char *));
quiz->answers[quiz->nAnswers - 1] = answer;
if (correct)
{
quiz->correctIdx = quiz->nAnswers - 1;
}
}
}
CWN3DLoadQuizzes(map, languageBuf);
free(languageBuf);
}

Expand Down Expand Up @@ -419,6 +388,7 @@ void CWFree(CWolfMap *map)
{
CWN3DQuizFree(&map->quizzes[i]);
}
free(map->quizzes);
memset(map, 0, sizeof *map);
}
static void LevelFree(CWLevel *level);
Expand Down Expand Up @@ -541,6 +511,50 @@ const char *CWGetDescription(CWolfMap *map, const int spearMission)
return NULL;
}

void CWN3DLoadQuizzes(CWolfMap *map, const char *languageBuf)
{
// May be reloading quizzes
for (int i = 0; i < map->nQuizzes; i++)
{
CWN3DQuizFree(&map->quizzes[i]);
}
free(map->quizzes);
map->quizzes = NULL;
map->nQuizzes = 0;
for (int q = 1;; q++)
{
char *question = CWLevelN3DLoadQuizQuestion(languageBuf, q);
if (question == NULL)
{
break;
}
map->nQuizzes++;
map->quizzes =
realloc(map->quizzes, map->nQuizzes * sizeof(CWN3DQuiz));
CWN3DQuiz *quiz = &map->quizzes[map->nQuizzes - 1];
memset(quiz, 0, sizeof *quiz);
quiz->question = question;
for (char a = 'A';; a++)
{
bool correct = false;
char *answer =
CWLevelN3DLoadQuizAnswer(languageBuf, q, a, &correct);
if (answer == NULL)
{
break;
}
quiz->nAnswers++;
quiz->answers =
realloc(quiz->answers, quiz->nAnswers * sizeof(char *));
quiz->answers[quiz->nAnswers - 1] = answer;
if (correct)
{
quiz->correctIdx = quiz->nAnswers - 1;
}
}
}
}

int CWGetAudioSampleRate(const CWolfMap *map)
{
switch (map->type)
Expand Down
2 changes: 2 additions & 0 deletions src/cdogs/cwolfmap/cwolfmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ void CWFree(CWolfMap *map);

const char *CWGetDescription(CWolfMap *map, const int spearMission);

void CWN3DLoadQuizzes(CWolfMap *map, const char *languageBuf);

int CWGetAudioSampleRate(const CWolfMap *map);

typedef enum
Expand Down
2 changes: 1 addition & 1 deletion src/cdogs/cwolfmap/n3d.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ char *CWLevelN3DLoadQuizQuestion(const char *buf, const int quiz);
char *CWLevelN3DLoadQuizAnswer(
const char *buf, const int quiz, const char answer, bool *correct);

void CWN3DQuizFree(CWN3DQuiz *quiz);
void CWN3DQuizFree(CWN3DQuiz *quiz);
49 changes: 1 addition & 48 deletions src/cdogs/map_archive.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@
#include "pickup.h"
#include "player_template.h"

static char *ReadFileIntoBuf(const char *path, const char *mode, long *len);

static json_t *ReadArchiveJSON(const char *archive, const char *filename);
int MapNewScanArchive(const char *filename, char **title, int *numMissions)
{
Expand Down Expand Up @@ -198,8 +196,7 @@ static json_t *ReadArchiveJSON(const char *archive, const char *filename)
json_t *root = NULL;
char path[CDOGS_PATH_MAX];
sprintf(path, "%s/%s", archive, filename);
long len;
char *buf = ReadFileIntoBuf(path, "rb", &len);
char *buf = ReadFileIntoBuf(path, "rb");
if (buf == NULL)
goto bail;
const enum json_error e = json_parse_document(&root, buf);
Expand Down Expand Up @@ -233,50 +230,6 @@ static void LoadArchivePics(PicManager *pm, map_t cc, const char *archive)
CharSpriteClassesLoadDir(cc, archive);
}

static char *ReadFileIntoBuf(const char *path, const char *mode, long *len)
{
char *buf = NULL;
FILE *f = fopen(path, mode);
if (f == NULL)
{
goto bail;
}

// Read into buffer
if (fseek(f, 0L, SEEK_END) != 0)
{
goto bail;
}
*len = ftell(f);
if (*len == -1)
{
goto bail;
}
CCALLOC(buf, *len + 1);
if (fseek(f, 0L, SEEK_SET) != 0)
{
goto bail;
}
if (fread(buf, 1, *len, f) == 0)
{
goto bail;
}

goto end;

bail:
CFREE(buf);
buf = NULL;

end:
if (f != NULL && fclose(f) != 0)
{
LOG(LM_MAP, LL_ERROR, "Cannot close file %s: %s", path,
strerror(errno));
}
return buf;
}

static json_t *SaveMissions(CArray *a);
int MapArchiveSave(const char *filename, CampaignSetting *c)
{
Expand Down
88 changes: 88 additions & 0 deletions src/cdogs/map_wolf.c
Original file line number Diff line number Diff line change
Expand Up @@ -3541,3 +3541,91 @@ static bool TryLoadCampaign(CampaignList *list, const char *path)
}
return false;
}

void MapWolfN3DCheckAndLoadCustomQuiz(
const Campaign *c, const CArray *playerDatas)
{
// Special case for N3D: Epic of Gilgamesh quiz easter egg
// This code is pretty cursed
if (strcmp(c->Setting.Title, "Super 2D Noah's Ark") != 0)
{
return;
}
bool hasGilgameshName = false;
CA_FOREACH(const PlayerData, p, *playerDatas)
if (Stricmp(p->name, "Gilgamesh") == 0 ||
Stricmp(p->name, "Enkidu") == 0 ||
Stricmp(p->name, "Utnapishtim") == 0 ||
Stricmp(p->name, "Ziusudra") == 0 ||
Stricmp(p->name, "Atra-Hasis") == 0 ||
Stricmp(p->name, "Atrahasis") == 0)
{
hasGilgameshName = true;
break;
}
CA_FOREACH_END()
if (!hasGilgameshName)
{
return;
}

// Load new quizzes
char pathBuf[CDOGS_PATH_MAX];
GetDataFilePath(pathBuf, WOLF_DATA_DIR "N3Ddata.cdogscpn/language.enu");
char *languageBuf = ReadFileIntoBuf(pathBuf, "r");
CWolfMap map;
memset(&map, 0, sizeof map);
CWN3DLoadQuizzes(&map, languageBuf);
free(languageBuf);

// Copy the effects from the "scroll" pickup
const PickupClass *scroll = StrPickupClass("scroll");
const PickupEffect *menuEffect = CArrayGet(&scroll->Effects, 0);
const CArray *correctEffects =
&((const PickupMenuItem *)CArrayGet(&menuEffect->u.Menu.Items, 0))
->Effects;
const CArray *wrongEffects =
&((const PickupMenuItem *)CArrayGet(&menuEffect->u.Menu.Items, 1))
->Effects;

// Replace the scroll pickups with the quizzes
for (int i = 0;; i++)
{
char buf[256];
sprintf(buf, "scroll+%d", i);
PickupClass *c = StrPickupClass(buf);
if (c == NULL)
{
break;
}
CA_FOREACH(PickupEffect, e, c->Effects)
PickupEffectTerminate(e);
CA_FOREACH_END()
CArrayClear(&c->Effects);

PickupEffect e;
memset(&e, 0, sizeof e);
e.Type = PICKUP_MENU;
const CWN3DQuiz *quiz = &map.quizzes[i];
CSTRDUP(e.u.Menu.Text, quiz->question);

CArrayInit(&e.u.Menu.Items, sizeof(PickupMenuItem));
for (int j = 0; j < quiz->nAnswers; j++)
{
PickupMenuItem m;
PickupMenuItemInit(&m);
CSTRDUP(m.Text, quiz->answers[j]);
const CArray *effects =
j == quiz->correctIdx ? correctEffects : wrongEffects;
CA_FOREACH(const PickupEffect, pe, *effects)
PickupEffect ec = PickupEffectCopy(pe);
CArrayPushBack(&m.Effects, &ec);
CA_FOREACH_END()
CArrayPushBack(&e.u.Menu.Items, &m);
}

CArrayPushBack(&c->Effects, &e);
}

CWFree(&map);
}
5 changes: 4 additions & 1 deletion src/cdogs/map_wolf.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
C-Dogs SDL
A port of the legendary (and fun) action/arcade cdogs.
Copyright (c) 2020-2021 Cong Xu
Copyright (c) 2020-2021, 2024 Cong Xu
All rights reserved.
Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -40,3 +40,6 @@ int MapWolfLoad(
const char *filename, const int spearMission, CampaignSetting *c);

void MapWolfLoadCampaignsFromSystem(CampaignList *list);

void MapWolfN3DCheckAndLoadCustomQuiz(
const Campaign *c, const CArray *playerDatas);
3 changes: 1 addition & 2 deletions src/cdogs/pickup_class.c
Original file line number Diff line number Diff line change
Expand Up @@ -200,15 +200,14 @@ PickupEffect PickupEffectCopy(const PickupEffect *e)
}
return out;
}
static void PickupEffectTerminate(PickupEffect *e);
static void PickupMenuItemTerminate(PickupMenuItem *m)
{
CFREE(m->Text);
CA_FOREACH(PickupEffect, e, m->Effects)
PickupEffectTerminate(e);
CA_FOREACH_END()
}
static void PickupEffectTerminate(PickupEffect *e)
void PickupEffectTerminate(PickupEffect *e)
{
switch (e->Type)
{
Expand Down
2 changes: 2 additions & 0 deletions src/cdogs/pickup_class.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ void PickupMenuItemInit(PickupMenuItem *m);
PickupEffect PickupEffectCopy(const PickupEffect *e);
void PickupClassInit(PickupClass *c);

void PickupEffectTerminate(PickupEffect *e);

void PickupClassesInit(
PickupClasses *classes, const char *filename, const AmmoClasses *ammo,
const WeaponClasses *guns);
Expand Down
47 changes: 46 additions & 1 deletion src/cdogs/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
This file incorporates work covered by the following copyright and
permission notice:
Copyright (c) 2013-2017, 2019-2022 Cong Xu
Copyright (c) 2013-2017, 2019-2022, 2024 Cong Xu
All rights reserved.
Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -62,6 +62,7 @@

#include "events.h"
#include "joystick.h"
#include "log.h"
#include "sys_config.h"

bool gTrue = true;
Expand Down Expand Up @@ -637,3 +638,47 @@ int Pulse256(const int t)
}
return alphaUnscaled;
}

char *ReadFileIntoBuf(const char *path, const char *mode)
{
char *buf = NULL;
FILE *f = fopen(path, mode);
if (f == NULL)
{
goto bail;
}

// Read into buffer
if (fseek(f, 0L, SEEK_END) != 0)
{
goto bail;
}
long len = ftell(f);
if (len == -1)
{
goto bail;
}
CCALLOC(buf, len + 1);
if (fseek(f, 0L, SEEK_SET) != 0)
{
goto bail;
}
if (fread(buf, 1, len, f) == 0)
{
goto bail;
}

goto end;

bail:
CFREE(buf);
buf = NULL;

end:
if (f != NULL && fclose(f) != 0)
{
LOG(LM_MAIN, LL_ERROR, "Cannot close file %s: %s", path,
strerror(errno));
}
return buf;
}
4 changes: 3 additions & 1 deletion src/cdogs/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
This file incorporates work covered by the following copyright and
permission notice:
Copyright (c) 2013-2017, 2019-2023 Cong Xu
Copyright (c) 2013-2017, 2019-2024 Cong Xu
All rights reserved.
Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -249,3 +249,5 @@ typedef enum
} PlacementAccessFlags;

int Pulse256(const int t);

char *ReadFileIntoBuf(const char *path, const char *mode);
Loading

0 comments on commit b26a146

Please sign in to comment.