LibreWands/Source/engineMaps.c

706 lines
19 KiB
C

// This file is part of LibreWands.
// LibreWands is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
// LibreWands is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along with LibreWands. If not, see https://www.gnu.org/licenses/.
// Add
// a
// new
// Base
// tile
int addBase()
{
// Allocate space for the new tile.
map[aMap].nBase++;
map[aMap].Base = realloc(map[aMap].Base, map[aMap].nBase * sizeof(struct Base));
// If this fails, do nothing.
if (map[aMap].Base == NULL)
{
map[aMap].nBase--;
return 1;
}
// Otherwise, set our values
map[aMap].Base[map[aMap].nBase - 1].x = x + (xmax / 2);
map[aMap].Base[map[aMap].nBase - 1].y = y + (ymax / 2);
map[aMap].Base[map[aMap].nBase - 1].t = tip;
map[aMap].Base[map[aMap].nBase - 1].c = tipColor;
map[aMap].Base[map[aMap].nBase - 1].walk = tipWalk;
map[aMap].Base[map[aMap].nBase - 1].active = 1;
// End gracefully
return 0;
}
// Add
// a
// new
// Info
// tile
int addInfo()
{
char buffer1[8] = "";
char buffer2[1] = "";
// Allocate space for the new tile.
map[aMap].nInfo++;
map[aMap].Info = realloc(map[aMap].Info, map[aMap].nInfo * sizeof(struct Info));
// If this fails, do nothing.
if (map[aMap].Info == NULL)
{
map[aMap].nInfo--;
return 1;
}
// Get our dialog
echo();
mvprintw(3, 0, "What character would you like to print? ");
getnstr(buffer2, 1);
mvprintw(4, 0, "What colour code would you like to use? ");
getnstr(buffer1, 8);
mvprintw(5, 0, "What would you like the sign to say? ");
getnstr(map[aMap].Info[map[aMap].nInfo - 1].dialog, 255);
// Otherwise, set our values
map[aMap].Info[map[aMap].nInfo - 1].x = x + (xmax / 2);
map[aMap].Info[map[aMap].nInfo - 1].y = y + (ymax / 2);
map[aMap].Info[map[aMap].nInfo - 1].c = atoi(buffer1);
map[aMap].Info[map[aMap].nInfo - 1].t = buffer2[0];
map[aMap].Info[map[aMap].nInfo - 1].active = 1;
// End gracefully
return 0;
}
// Add
// a
// new
// Item
// tile
int addItem()
{
char buffer1[1];
char buffer2[8];
char buffer3[8];
// Allocate space for the new tile.
map[aMap].nItem++;
map[aMap].Item = realloc(map[aMap].Item, map[aMap].nItem * sizeof(struct Item));
// If this fails, do nothing.
if (map[aMap].Item == NULL)
{
map[aMap].nItem--;
return 1;
}
// Get our item ID#
echo();
mvprintw(3, 0, "What character would you like to print? ");
getnstr(buffer1, 1);
mvprintw(4, 0, "What colour code would you like to use? ");
getnstr(buffer2, 8);
mvprintw(5, 0, "What item is this? (ID#) ");
getnstr(buffer3, 8);
map[aMap].Item[map[aMap].nItem - 1].ID = atoi(buffer3);
// Otherwise, set our values
map[aMap].Item[map[aMap].nItem - 1].x = x + (xmax / 2);
map[aMap].Item[map[aMap].nItem - 1].y = y + (ymax / 2);
map[aMap].Item[map[aMap].nItem - 1].t = buffer1[0];
map[aMap].Item[map[aMap].nItem - 1].c = atoi(buffer2);
map[aMap].Item[map[aMap].nItem - 1].active = 1;
// End gracefully
return 0;
}
// Add
// a
// new
// Door
// tile
int addDoor()
{
char buffer1[1];
char buffer2[8];
char buffer3[8];
char buffer4[8];
char buffer5[8];
char buffer6[8];
// Allocate space for the new tile.
map[aMap].nDoor++;
map[aMap].Door = realloc(map[aMap].Door, map[aMap].nDoor * sizeof(struct Door));
// If this fails, do nothing.
if (map[aMap].Door == NULL)
{
map[aMap].nDoor--;
return 1;
}
// Get our info
echo();
mvprintw(3, 0, "What character would you like to print? ");
getnstr(buffer1, 1);
mvprintw(4, 0, "What colour code would you like to use? ");
getnstr(buffer2, 8);
mvprintw(5, 0, "Which map will this door go to? ");
getnstr(buffer3, 8);
mvprintw(6, 0, "What X value? ");
getnstr(buffer4, 8);
mvprintw(7, 0, "What Y value? ");
getnstr(buffer5, 8);
mvprintw(8, 0, "Is this door locked? ");
getnstr(buffer6, 8);
// Otherwise, set our values
map[aMap].Door[map[aMap].nDoor - 1].x = x + (xmax / 2);
map[aMap].Door[map[aMap].nDoor - 1].y = y + (ymax / 2);
map[aMap].Door[map[aMap].nDoor - 1].t = buffer1[0];
map[aMap].Door[map[aMap].nDoor - 1].c = atoi(buffer2);
map[aMap].Door[map[aMap].nDoor - 1].lock = atoi(buffer6);
map[aMap].Door[map[aMap].nDoor - 1].ID = atoi(buffer3);
map[aMap].Door[map[aMap].nDoor - 1].nx = atoi(buffer4);
map[aMap].Door[map[aMap].nDoor - 1].ny = atoi(buffer5);
map[aMap].Door[map[aMap].nDoor - 1].active = 1;
// End gracefully
return 0;
}
// Add
// a
// new
// Char
// tile
int addChar()
{
char buffer1[1];
char buffer2[1];
char buffer3[8];
char buffer4[8];
char buffer5[8];
char buffer6[8];
char buffer7[8];
char buffer8[8];
char buffer9[8];
char bufferA[8];
char bufferB[8];
char bufferC[8];
char bufferD[8];
char bufferE[8];
// Allocate space for the new tile.
map[aMap].nChar++;
map[aMap].Char = realloc(map[aMap].Char, map[aMap].nChar * sizeof(struct Char));
// If this fails, do nothing.
if (map[aMap].Char == NULL)
{
map[aMap].nChar--;
return 1;
}
// Get our info
echo();
mvprintw(3, 0, "What character would you like to print? ");
getnstr(bufferD, 8);
mvprintw(4, 0, "What colour code would you like to use? ");
getnstr(bufferE, 8);
mvprintw(5, 0, "Is this guy passive or aggressive? (1 = aggressive, 0 = passive) ");
getnstr(buffer1, 1);
mvprintw(6, 0, "Does he wander or stay still? (1 = wanders, 0 = still) ");
getnstr(buffer2, 1);
mvprintw(7, 0, "What is his/her name? ");
getnstr(map[aMap].Char[map[aMap].nChar - 1].name, 256);
mvprintw(8, 0, "What do they say when they want to fight? ");
getnstr(map[aMap].Char[map[aMap].nChar - 1].dialog1, 256);
mvprintw(9, 0, "What do they say when they don't want to fight? ");
getnstr(map[aMap].Char[map[aMap].nChar - 1].dialog2, 256);
mvprintw(10, 0, "What's the 1st monster they carry? (ID#) ");
getnstr(buffer3, 8);
mvprintw(11, 0, "What's the 2nd monster they carry? (ID#) ");
getnstr(buffer4, 8);
mvprintw(12, 0, "What's the 3rd monster they carry? (ID#) ");
getnstr(buffer5, 8);
mvprintw(13, 0, "What's the 4th monster they carry? (ID#) ");
getnstr(buffer6, 8);
mvprintw(14, 0, "What's the 5th monster they carry? (ID#) ");
getnstr(buffer7, 8);
mvprintw(15, 0, "What level is the 1st monster they carry? (#) ");
getnstr(buffer8, 8);
mvprintw(16, 0, "What level is the 2nd monster they carry? (#) ");
getnstr(buffer9, 8);
mvprintw(17, 0, "What level is the 3rd monster they carry? (#) ");
getnstr(bufferA, 8);
mvprintw(18, 0, "What level is the 4th monster they carry? (#) ");
getnstr(bufferB, 8);
mvprintw(19, 0, "What level is the 5th monster they carry? (#) ");
getnstr(bufferC, 8);
// Otherwise, set our values
map[aMap].Char[map[aMap].nChar - 1].x = x + (xmax / 2);
map[aMap].Char[map[aMap].nChar - 1].y = y + (ymax / 2);
map[aMap].Char[map[aMap].nChar - 1].t = bufferD[0];
map[aMap].Char[map[aMap].nChar - 1].c = atoi(bufferE);
map[aMap].Char[map[aMap].nChar - 1].type = atoi(buffer1);
map[aMap].Char[map[aMap].nChar - 1].move = atoi(buffer2);
map[aMap].Char[map[aMap].nChar - 1].mon[0].type = atoi(buffer3);
map[aMap].Char[map[aMap].nChar - 1].mon[1].type = atoi(buffer4);
map[aMap].Char[map[aMap].nChar - 1].mon[2].type = atoi(buffer5);
map[aMap].Char[map[aMap].nChar - 1].mon[3].type = atoi(buffer6);
map[aMap].Char[map[aMap].nChar - 1].mon[4].type = atoi(buffer7);
map[aMap].Char[map[aMap].nChar - 1].mon[0].level = atoi(buffer8);
map[aMap].Char[map[aMap].nChar - 1].mon[1].level = atoi(buffer9);
map[aMap].Char[map[aMap].nChar - 1].mon[2].level = atoi(bufferA);
map[aMap].Char[map[aMap].nChar - 1].mon[3].level = atoi(bufferB);
map[aMap].Char[map[aMap].nChar - 1].mon[4].level = atoi(bufferC);
map[aMap].Char[map[aMap].nChar - 1].active = 1;
// End gracefully
return 0;
}
int delTile()
{
// Deactivate any tiles that our cursor is over
for (int C = 0; C < map[aMap].nBase; C++)
if ((map[aMap].Base[C].x == x + (xmax / 2)) &&
(map[aMap].Base[C].y == y + (ymax / 2)))
map[aMap].Base[C].active = 0;
for (int C = 0; C < map[aMap].nInfo; C++)
if ((map[aMap].Info[C].x == x + (xmax / 2)) &&
(map[aMap].Info[C].y == y + (ymax / 2)))
map[aMap].Info[C].active = 0;
for (int C = 0; C < map[aMap].nItem; C++)
if ((map[aMap].Item[C].x == x + (xmax / 2)) &&
(map[aMap].Item[C].y == y + (ymax / 2)))
map[aMap].Item[C].active = 0;
for (int C = 0; C < map[aMap].nDoor; C++)
if ((map[aMap].Door[C].x == x + (xmax / 2)) &&
(map[aMap].Door[C].y == y + (ymax / 2)))
map[aMap].Door[C].active = 0;
for (int C = 0; C < map[aMap].nChar; C++)
if ((map[aMap].Char[C].x == x + (xmax / 2)) &&
(map[aMap].Char[C].y == y + (ymax / 2)))
map[aMap].Char[C].active = 0;
return 0;
}
// Change
// our
// tooltip
// for
// a
// different
// one
int turnTip()
{
char buffer2[1] = "";
char buffer3[8] = "";
char buffer4[1] = "";
uint_fast8_t colr = 0;
uint_fast8_t walk = 0;
echo();
// Ask our necessary details.
mvprintw(3, 0, "What character would you like to print? ");
getnstr(buffer2, 1);
mvprintw(4, 0, "What colour code would you like to use? ");
getnstr(buffer3, 8);
colr = atoi(buffer3);
mvprintw(5, 0, "Are these tiles walkable? (1 = yes, 0 = no) ");
getnstr(buffer4, 1);
walk = atoi(buffer4);
// Set our variables to our aquired values
tipColor = colr;
tipWalk = walk;
tip = buffer2[0];
// end gracefully
return 0;
}
// Allocate
// memory
// for
// our
// internal
// map
int newMap()
{
char buffer[16] = "";
uint_fast8_t n = 0;
echo();
// While we don't have a nonzero answer
while (n == 0)
{
// Prompt for the number of maps we want
mvprintw(1, 0, "How many maps would you like to allocate? ");
getnstr(buffer, 16);
n = atoi(buffer);
}
// Allocate the needed memory
map = malloc(n * sizeof(struct maps));
// On failure, report error.
if (map == NULL)
{
mvprintw(2, 0, "Unable to allocate memory.");
getnstr(NULL, 0);
return 1;
}
else
{
nMap = n;
}
return 0;
}
int saveMap()
{
echo();
char buffer[256] = "";
// Prompt for our file name
mvprintw(3, 0, "Save name? ");
getnstr(buffer, 256);
// Open the file. Exit on failure.
FILE *fp = fopen(buffer, "w");
if (fp == NULL)
return 1;
fprintf(fp, "<document maps=\"%i\">\n", nMap);
// For every map
for (uint_fast8_t C = 0; C < nMap; C++)
{
fprintf(fp,
"\t<map bases=\"%i\" infos=\"%i\" items=\"%i\" doors=\"%i\" "
"chars=\"%i\">\n",
map[C].nBase, map[C].nInfo, map[C].nItem, map[C].nDoor, map[C].nChar);
// for every active base
for (uint_fast8_t B = 0; B < map[C].nBase; B++)
{
if (map[C].Base[B].active)
{
fprintf(fp,
"\t\t<base x=\"%li\" y=\"%li\" t=\"%i\" c=\"%i\" "
"walk=\"%i\" />\n",
map[C].Base[B].x, map[C].Base[B].y, map[C].Base[B].t,
map[C].Base[B].c, map[C].Base[B].walk);
}
}
// for every active info
for (uint_fast8_t B = 0; B < map[C].nInfo; B++)
{
if (map[C].Info[B].active)
{
fprintf(fp,
"\t\t<info x=\"%li\" y=\"%li\" t=\"%i\" c=\"%i\" "
"dialog=\"%s \" />\n",
map[C].Info[B].x, map[C].Info[B].y, map[C].Info[B].t,
map[C].Info[B].c, map[C].Info[B].dialog);
}
}
// for every active item
for (uint_fast8_t B = 0; B < map[C].nItem; B++)
{
if (map[C].Item[B].active)
{
fprintf(fp,
"\t\t<item x=\"%li\" y=\"%li\" t=\"%i\" c=\"%i\" ID=\"%i\" "
"/>\n",
map[C].Item[B].x, map[C].Item[B].y, map[C].Item[B].t,
map[C].Item[B].c, map[C].Item[B].ID);
}
}
// for every active door
for (uint_fast8_t B = 0; B < map[C].nDoor; B++)
{
if (map[C].Door[B].active)
{
fprintf(
fp,
"\t\t<door x=\"%li\" y=\"%li\" t=\"%i\" c=\"%i\" lock=\"%i\" "
"ID=\"%i\" nx=\"%li\" ny=\"%li\" />\n",
map[C].Door[B].x, map[C].Door[B].y, map[C].Door[B].t,
map[C].Door[B].c, map[C].Door[B].lock, map[C].Door[B].ID,
map[C].Door[B].nx, map[C].Door[B].ny);
}
}
// for every active char
for (uint_fast8_t B = 0; B < map[C].nChar; B++)
{
if (map[C].Char[B].active)
{
fprintf(
fp,
"\t\t<char x=\"%li\" y=\"%li\" t=\"%i\" c=\"%i\" type=\"%i\" "
"move=\"%i\" name=\"%s\" dialog1=\"%s\" dialog2=\"%s\">\n",
map[C].Char[B].x, map[C].Char[B].y, map[C].Char[B].t,
map[C].Char[B].c, map[C].Char[B].type, map[C].Char[B].move,
map[C].Char[B].name, map[C].Char[B].dialog1,
map[C].Char[B].dialog2);
// Add all the carried monsters
for (uint_fast8_t A = 0; A < 5; A++)
{
fprintf(fp, "\t\t\t<mon type=\"%i\" level=\"%i\" />\n",
map[C].Char[B].mon[A].type,
map[C].Char[B].mon[A].level);
}
fprintf(fp, "\t\t</char>\n");
}
}
fprintf(fp, "\t</map>\n");
}
fprintf(fp, "</document>\n");
fclose(fp);
return 0;
}
int loadMap()
{
int iMap = 0;
int iBase = 0;
int iInfo = 0;
int iItem = 0;
int iDoor = 0;
int iChar = 0;
char buffer[256] = "";
char substr[256] = "";
FILE *fp;
// Prompt for our file name
echo();
mvprintw(3, 0, "Load name? ");
getnstr(buffer, 256);
// Open file. Exit on failure
fp = fopen(buffer, "r");
if (fp == NULL)
{
getnstr(buffer, 1);
return 1;
}
// While we haven't reached the end of our file
while (fgets(buffer, 256, fp) != NULL)
{
// If we're given a <document>
if (strcmp(strncpy(substr, buffer, 5), "<docu") == 0)
{
// Get our number of maps
sscanf(buffer, "<document maps=\"%hhi\">", &nMap);
// Allocate our memory
map = realloc(map, nMap * sizeof(struct maps));
if (map == NULL)
return 0;
// This makes it work for some reason.
strncpy(buffer, "", 256);
}
// If we're given a <map>
if (strcmp(strncpy(substr, buffer, 4), "\t<map") == 0)
{
// Get our bases, infos, items etc.
sscanf(buffer,
"\t<map bases=\"%hhi\" infos=\"%hhi\" items=\"%hhi\" doors=\"%hhi\""
" chars=\"%hhi\">",
&map[iMap].nBase, &map[iMap].nInfo, &map[iMap].nItem,
&map[iMap].nDoor, &map[iMap].nChar);
// Allocate our memory
map[iMap].Base =
realloc(map[iMap].Base, map[iMap].nBase * sizeof(struct Base));
if (map[iMap].Base == NULL)
return 0;
map[iMap].Info =
realloc(map[iMap].Info, map[iMap].nInfo * sizeof(struct Info));
if (map[iMap].Base == NULL)
return 0;
map[iMap].Item =
realloc(map[iMap].Item, map[iMap].nItem * sizeof(struct Item));
if (map[iMap].Item == NULL)
return 0;
map[iMap].Door =
realloc(map[iMap].Door, map[iMap].nDoor * sizeof(struct Door));
if (map[iMap].Door == NULL)
return 0;
map[iMap].Char =
realloc(map[iMap].Char, map[iMap].nChar * sizeof(struct Char));
if (map[iMap].Char == NULL)
return 0;
// This makes it work for some reason.
strncpy(buffer, "", 256);
}
// If we're given a </map>
if (strcmp(strncpy(substr, buffer, 7), "\t</map>") == 0)
{
// This makes it work for some reason.
strncpy(buffer, "", 256);
iMap++;
iBase = 0;
iInfo = 0;
iItem = 0;
iDoor = 0;
iChar = 0;
}
// If we're given a <base>
if (strcmp(strncpy(substr, buffer, 7), "\t\t<base") == 0)
{
// Get our x, y, t, c, etc.
sscanf(buffer,
"\t\t<base x=\"%li\" y=\"%li\" t=\"%hhi\" c=\"%hhi\" walk=\"%hhi\""
" />",
&map[iMap].Base[iBase].x, &map[iMap].Base[iBase].y,
&map[iMap].Base[iBase].t, &map[iMap].Base[iBase].c,
&map[iMap].Base[iBase].walk);
map[iMap].Base[iBase].active = 1;
// This makes it work for some reason.
strncpy(buffer, "", 256);
// Increment our values
iBase++;
}
// If we're given a <info>
if (strcmp(strncpy(substr, buffer, 7), "\t\t<info") == 0)
{
// Get our x, y, t, c, etc.
sscanf(buffer,
"\t\t<info x=\"%li\" y=\"%li\" t=\"%hhi\" c=\"%hhi\""
" dialog=\"%255[^\"]\" />",
&map[iMap].Info[iInfo].x, &map[iMap].Info[iInfo].y,
&map[iMap].Info[iInfo].t, &map[iMap].Info[iInfo].c,
map[iMap].Info[iInfo].dialog);
map[iMap].Info[iInfo].active = 1;
// Increment our values
iInfo++;
}
// If we're given a <item>
if (strcmp(strncpy(substr, buffer, 7), "\t\t<item") == 0)
{
// Get our x, y, t, c, etc.
sscanf(buffer,
"\t\t<item x=\"%li\" y=\"%li\" t=\"%hhi\" c=\"%hhi\" ID=\"%hhi\""
" />",
&map[iMap].Item[iItem].x, &map[iMap].Item[iItem].y,
&map[iMap].Item[iItem].t, &map[iMap].Item[iItem].c,
&map[iMap].Item[iItem].ID);
map[iMap].Item[iItem].active = 1;
// Increment our values
iItem++;
}
// If we're given a <door>
if (strcmp(strncpy(substr, buffer, 7), "\t\t<door") == 0)
{
// Get our x, y, t, c, etc.
sscanf(buffer,
"\t\t<door x=\"%li\" y=\"%li\" t=\"%hhi\" c=\"%hhi\" lock=\"%hhi\""
" ID=\"%hhi\" nx=\"%li\" ny=\"%li\" />",
&map[iMap].Door[iDoor].x, &map[iMap].Door[iDoor].y,
&map[iMap].Door[iDoor].t, &map[iMap].Door[iDoor].c,
&map[iMap].Door[iDoor].lock, &map[iMap].Door[iDoor].ID,
&map[iMap].Door[iDoor].nx, &map[iMap].Door[iDoor].ny);
map[iMap].Door[iDoor].active = 1;
// This makes it work for some reason.
strncpy(buffer, "", 256);
// Increment our values
iDoor++;
}
// If we're given a <char>
if (strcmp(strncpy(substr, buffer, 7), "\t\t<char") == 0)
{
// Get our x, y, t, c, etc.
sscanf(buffer,
"\t\t<char x=\"%li\" y=\"%li\" t=\"%hhi\" c=\"%hhi\" type=\"%hhi\""
" move=\"%hhi\" name=\"%255[^\"]\" dialog1=\"%255[^\"]\""
" dialog2=\"%255[^\"]\">",
&map[iMap].Char[iChar].x, &map[iMap].Char[iChar].y,
&map[iMap].Char[iChar].t, &map[iMap].Char[iChar].c,
&map[iMap].Char[iChar].type, &map[iMap].Char[iChar].move,
map[iMap].Char[iChar].name, map[iMap].Char[iChar].dialog1,
map[iMap].Char[iChar].dialog2);
map[iMap].Char[iChar].active = 1;
for (int C = 0; C < 5; C++)
{
// Get our new line
if (fgets(buffer, 256, fp) == NULL)
return 1;
// Get our type and level for each monster
sscanf(buffer, "\t\t\t<mon type=\"%hhi\" level=\"%hhi\" />",
&map[iMap].Char[iChar].mon[C].type,
&map[iMap].Char[iChar].mon[C].level);
}
// This makes things work for some reason.
strncpy(buffer, "", 256);
}
// If we get an </char>, increment our char value.
if (strcmp(strncpy(substr, buffer, 7), "\t\t</char>") == 0)
{
// This makes things work for some reason.
strncpy(buffer, "", 256);
iChar++;
}
// If we get an </document>,
if (strcmp(strncpy(substr, buffer, 7), "\t\t</docu") == 0)
{
// This makes things work for some reason.
strncpy(buffer, "", 256);
}
}
return 0;
}