├── .gitignore ├── MoonbaseConsole ├── icon1.ico ├── Template.thm ├── Template.wiz ├── MoonbaseConsole.aps ├── MoonbaseConsole.opt ├── crc.h ├── KattonGen.h ├── SpiffGen.h ├── Base64Encode.h ├── StdAfx.cpp ├── MoonbaseConsole.dsw ├── crc.cpp ├── StdAfx.h ├── MoonbaseConsole.sln ├── GameInfo.h ├── resource.h ├── MoonbaseConsole.plg ├── Base64Encode.cpp ├── README.TXT ├── MoonbaseConsole.dsp ├── MoonbaseConsole.vcproj ├── MoonbaseConsole.rc ├── SpiffGen.cpp └── KattonGen.cpp ├── Common ├── globals.h ├── MBCMapImage.h ├── mbcmif.h └── mbcmif.cpp ├── todo.txt ├── Makefile ├── LICENSE.txt ├── README.md └── MC_README.TXT /.gitignore: -------------------------------------------------------------------------------- 1 | *.exe 2 | *.o 3 | *.ini 4 | *.swp 5 | *~ 6 | -------------------------------------------------------------------------------- /MoonbaseConsole/icon1.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michaelbarlow7/moonbase-console/HEAD/MoonbaseConsole/icon1.ico -------------------------------------------------------------------------------- /MoonbaseConsole/Template.thm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michaelbarlow7/moonbase-console/HEAD/MoonbaseConsole/Template.thm -------------------------------------------------------------------------------- /MoonbaseConsole/Template.wiz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michaelbarlow7/moonbase-console/HEAD/MoonbaseConsole/Template.wiz -------------------------------------------------------------------------------- /MoonbaseConsole/MoonbaseConsole.aps: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michaelbarlow7/moonbase-console/HEAD/MoonbaseConsole/MoonbaseConsole.aps -------------------------------------------------------------------------------- /MoonbaseConsole/MoonbaseConsole.opt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michaelbarlow7/moonbase-console/HEAD/MoonbaseConsole/MoonbaseConsole.opt -------------------------------------------------------------------------------- /MoonbaseConsole/crc.h: -------------------------------------------------------------------------------- 1 | #ifndef __CRC_H__ 2 | #define __CRC_H__ 3 | 4 | extern unsigned char crc8(unsigned char *ptr, register int len); 5 | 6 | #endif 7 | 8 | -------------------------------------------------------------------------------- /MoonbaseConsole/KattonGen.h: -------------------------------------------------------------------------------- 1 | #ifndef __KATTONGEN_H__ 2 | #define __KATTONGEN_H__ 3 | 4 | #include "GameInfo.h" 5 | 6 | void KattonGenerate(CGameInfo& gi, MBCMIF& mif); 7 | 8 | #endif -------------------------------------------------------------------------------- /MoonbaseConsole/SpiffGen.h: -------------------------------------------------------------------------------- 1 | #ifndef __SPIFFGEN_H__ 2 | #define __SPIFFGEN_H__ 3 | 4 | #include "GameInfo.h" 5 | 6 | void SpiffGenerate (CGameInfo& gi, MBCMIF& mif); 7 | 8 | #endif -------------------------------------------------------------------------------- /MoonbaseConsole/Base64Encode.h: -------------------------------------------------------------------------------- 1 | #ifndef __Base64Encode_H__ 2 | #define __Base64Encode_H__ 3 | 4 | 5 | 6 | void SecureBase64Encode(unsigned char *pby, int cby, char *psz, int cbszMax); 7 | bool SecureBase64Decode(unsigned char *pby, int cby, char *psz); 8 | 9 | 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /MoonbaseConsole/StdAfx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // MoonbaseConsole.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "StdAfx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /MoonbaseConsole/MoonbaseConsole.dsw: -------------------------------------------------------------------------------- 1 | Microsoft Developer Studio Workspace File, Format Version 6.00 2 | # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! 3 | 4 | ############################################################################### 5 | 6 | Project: "MoonbaseConsole"=".\MoonbaseConsole.dsp" - Package Owner=<4> 7 | 8 | Package=<5> 9 | {{{ 10 | }}} 11 | 12 | Package=<4> 13 | {{{ 14 | }}} 15 | 16 | ############################################################################### 17 | 18 | Global: 19 | 20 | Package=<5> 21 | {{{ 22 | }}} 23 | 24 | Package=<3> 25 | {{{ 26 | }}} 27 | 28 | ############################################################################### 29 | 30 | -------------------------------------------------------------------------------- /MoonbaseConsole/crc.cpp: -------------------------------------------------------------------------------- 1 | // I got this code from AT&T and changed it until I could read it, but the logic is theirs. 2 | 3 | unsigned char crc8 (unsigned char *ptr, int len) 4 | { 5 | static int tblInitialized = 0; 6 | static unsigned char crcReg, crcTbl[256]; 7 | unsigned long i, j, k; 8 | 9 | if( !tblInitialized ) 10 | { 11 | for( i=0; i < 256; i++ ) 12 | { 13 | j = i; 14 | for( k=8; k--; ) 15 | j = j & 0x80? (j << 1) ^ 0x0107 : j << 1; 16 | 17 | crcTbl[ i ] = (unsigned char)j; 18 | } 19 | 20 | tblInitialized = 1; 21 | } 22 | 23 | crcReg = 0; 24 | 25 | for( ;len--; ) 26 | crcReg = crcTbl[ crcReg ^ *ptr++ ]; 27 | 28 | return crcReg; 29 | } 30 | -------------------------------------------------------------------------------- /MoonbaseConsole/StdAfx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #if !defined(AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_) 7 | #define AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_ 8 | 9 | #if _MSC_VER > 1000 10 | #pragma once 11 | #endif // _MSC_VER > 1000 12 | 13 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 14 | 15 | #include 16 | 17 | 18 | // TODO: reference additional headers your program requires here 19 | 20 | //{{AFX_INSERT_LOCATION}} 21 | // Microsoft Visual C++ will insert additional declarations immediately before the previous line. 22 | 23 | #endif // !defined(AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_) 24 | -------------------------------------------------------------------------------- /Common/globals.h: -------------------------------------------------------------------------------- 1 | #ifndef __GLOBALS_H__ 2 | #define __GLOBALS_H__ 3 | 4 | 5 | 6 | #include 7 | 8 | 9 | 10 | #define MAX_TILE_COUNT 80 11 | 12 | typedef unsigned short WORD; 13 | typedef unsigned char BYTE; 14 | 15 | class CMapError 16 | { 17 | public: 18 | int m_nX; 19 | int m_nY; 20 | char m_szErrorDescription[128]; 21 | 22 | CMapError (int nX, int nY, char *psz) 23 | { 24 | m_nX = nX; 25 | m_nY = nY; 26 | strcpy(m_szErrorDescription, psz); 27 | } 28 | 29 | protected: 30 | CMapError () 31 | { 32 | } 33 | 34 | }; 35 | 36 | class CGenericError 37 | { 38 | public: 39 | char m_szErrorDescription[1068]; 40 | 41 | CGenericError (char *psz) 42 | { 43 | strcpy(m_szErrorDescription, psz); 44 | } 45 | 46 | protected: 47 | CGenericError () 48 | { 49 | } 50 | }; 51 | 52 | 53 | 54 | #endif -------------------------------------------------------------------------------- /MoonbaseConsole/MoonbaseConsole.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 10.00 3 | # Visual C++ Express 2008 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MoonbaseConsole", "MoonbaseConsole.vcproj", "{58509299-377E-4432-B142-E1C06715FD85}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win32 = Debug|Win32 9 | Release|Win32 = Release|Win32 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {58509299-377E-4432-B142-E1C06715FD85}.Debug|Win32.ActiveCfg = Debug|Win32 13 | {58509299-377E-4432-B142-E1C06715FD85}.Debug|Win32.Build.0 = Debug|Win32 14 | {58509299-377E-4432-B142-E1C06715FD85}.Release|Win32.ActiveCfg = Release|Win32 15 | {58509299-377E-4432-B142-E1C06715FD85}.Release|Win32.Build.0 = Release|Win32 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /todo.txt: -------------------------------------------------------------------------------- 1 | Just a running list of things I plan to do for this, so when I lose interest and pick it up again 9 months later I can see what needs to be done. A plus means it's done. 2 | 3 | + Add more IP address finder inputs 4 | + Implement change control dialog 5 | + Add (symmetrical) (asymmetrical) to Spiff and Katton respectively 6 | + Make it work with steam version/multiple versions of Windows 7 | + Put self in credits 8 | + Update readme with changes 9 | + Increase version number 10 | + Upload .exe to somewhere, possibly Dropbox? PDrive? Or use Github releases 11 | 12 | - Use a different UI framework cos this one is really annoying to work with (Qt?) 13 | -- I think I'll do this for the next version, I hate this current framework. I'm going to make version 2.2 workable (if possibly buggy) and then direct my efforts to making a Qt version for 3.0) 14 | 15 | - Toggle fullscreen from settings (I think this just requires access to C:\Windows\hegames.ini) 16 | - Be smart about finding .exe path 17 | -------------------------------------------------------------------------------- /MoonbaseConsole/GameInfo.h: -------------------------------------------------------------------------------- 1 | #ifndef __GAMEINFO_H__ 2 | #define __GAMEINFO_H__ 3 | 4 | #define SPIFF_GEN 1 5 | #define KATTON_GEN 2 6 | 7 | #pragma pack(push, 1) 8 | struct CGameInfo 9 | { 10 | unsigned int nMapSize : 7; 11 | unsigned int nGenerator : 3; 12 | unsigned int nVersion : 3; 13 | unsigned int nTileset : 3; 14 | unsigned int nTerrain : 4; 15 | unsigned int nWater : 4; 16 | unsigned int nEnergy : 4; 17 | unsigned short nSeed; 18 | unsigned char nIP1; 19 | unsigned char nIP2; 20 | unsigned char nIP3; 21 | unsigned char nIP4; 22 | /* union 23 | { 24 | unsigned long blanker; 25 | struct 26 | { 27 | BYTE cSpecials; 28 | BYTE nCliff; 29 | } SpiffData; 30 | struct 31 | { 32 | BYTE nSplotches; 33 | BYTE nLandFatness; 34 | BYTE nWater; 35 | BYTE nEnergy; 36 | } KattonData; 37 | } GeneratorData;*/ 38 | }; 39 | #pragma pack(pop) 40 | 41 | #endif -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # This Makefile will build Moonbase Console using MinGW 2 | # Simply typing "make" in the same directory as this file should build it 3 | 4 | OBJS=Common/mbcmif.o MoonbaseConsole/Base64Encode.o MoonbaseConsole/crc.o MoonbaseConsole/KattonGen.o MoonbaseConsole/SpiffGen.o MoonbaseConsole/StdAfx.o MoonbaseConsole/MoonbaseConsole.o MoonbaseConsole/resource.o 5 | 6 | UNAME := $(shell uname) 7 | 8 | ifeq ($(UNAME), Linux) 9 | INCLUDE_DIRS = -I./MoonbaseConsole -I./Common 10 | CC = i686-w64-mingw32-g++ 11 | else 12 | INCLUDE_DIRS = -I.\MoonbaseConsole -I.\Common 13 | CC = g++ 14 | endif 15 | 16 | WARNS = -Wall 17 | CFLAGS = -O2 -D _WIN32_IE=0x0500 -D WINVER=0x500 ${WARNS} 18 | LDFLAGS = -lcomctl32 -lws2_32 -lwininet -static -mwindows 19 | #RC = windres 20 | RC = i686-w64-mingw32-windres 21 | 22 | all : MoonbaseConsole.exe 23 | 24 | MoonbaseConsole.exe : ${OBJS} 25 | ${CC} -o "$@" ${OBJS} ${LDFLAGS} 26 | 27 | clean : 28 | rm *.exe MoonbaseConsole/*.o Common/*.o *.ini 29 | 30 | %.o : %.cpp 31 | ${CC} ${CFLAGS} ${INCLUDE_DIRS} -c $< -o $@ 32 | 33 | MoonbaseConsole/resource.o : MoonbaseConsole/MoonbaseConsole.rc 34 | ${RC} -i $< -o $@ 35 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Michael Barlow 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /Common/MBCMapImage.h: -------------------------------------------------------------------------------- 1 | #ifndef __MBCMAPIMAGE_H__ 2 | #define __MBCMAPIMAGE_H__ 3 | 4 | 5 | 6 | #include "globals.h" 7 | #include 8 | 9 | 10 | 11 | #pragma pack(push, 1) 12 | typedef struct tagPixelLoc 13 | { 14 | WORD xLoc; 15 | WORD yLoc; 16 | } PixelLoc; 17 | typedef struct tagEnergyPoolLoc 18 | { 19 | PixelLoc plLocation; 20 | PixelLoc plDummy; 21 | } EnergyPoolLoc; 22 | struct MBCMapImage 23 | { 24 | WORD wHeaderDummy; 25 | WORD cTilesX; 26 | WORD cTilesY; 27 | WORD nTileset; 28 | WORD cEnergyPools; 29 | WORD aaTiles[80][161]; 30 | BYTE aSpace1[230]; 31 | char szName[17]; 32 | BYTE aSpace2[25837]; 33 | EnergyPoolLoc aepLocs[49]; 34 | PixelLoc epLastPool; 35 | WORD wDummy; 36 | PixelLoc apl4PLocs[4]; // 2^0 37 | PixelLoc apl3PLocs[3]; // 2^1 38 | PixelLoc apl2PLocs[2]; // 2^2 39 | PixelLoc apl2v2PLocs[4]; // 2^3 40 | PixelLoc apl1v3PLocs[4]; // 2^4 41 | PixelLoc apl1v2PLocs[3]; // 2^5 42 | 43 | MBCMapImage() 44 | { 45 | memset(this, 0, sizeof(MBCMapImage)); 46 | 47 | nTileset = 1; 48 | memset((void *)apl4PLocs, 0xFF, sizeof(PixelLoc) * 20); 49 | szName[0] = 'N'; 50 | } 51 | }; 52 | #pragma pack(pop) 53 | 54 | 55 | 56 | #endif -------------------------------------------------------------------------------- /MoonbaseConsole/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Developer Studio generated include file. 3 | // Used by MoonbaseConsole.rc 4 | // 5 | #define IDD_DIALOG1 101 6 | #define IDI_ICON1 103 7 | #define IDB_BITMAP1 106 8 | #define IDD_DIALOG2 108 9 | #define IDD_DIALOG3 109 10 | #define IDR_WIZ1 110 11 | #define IDR_TXT1 113 12 | #define IDC_TXT1 114 13 | #define IDR_THM1 115 14 | #define IDC_BUTTON2 1003 15 | #define IDC_EDIT2 1004 16 | #define IDC_IPADDRESS1 1005 17 | #define IDC_BTN_HOST_GAME 1019 18 | #define IDC_SINGLE_GENERATE 1020 19 | #define IDC_SLIDER1 1023 20 | #define IDC_SLIDER2 1024 21 | #define IDC_SLIDER3 1025 22 | #define IDC_SLIDER4 1026 23 | #define IDC_SLIDER5 1027 24 | #define IDC_SLIDER6 1028 25 | #define IDC_CHECK1 1029 26 | #define IDC_CHECK2 1030 27 | #define IDC_CHECK3 1031 28 | #define IDC_CHECK4 1032 29 | #define IDC_CHECK5 1033 30 | #define IDC_CHECK6 1034 31 | #define IDC_BUTTON1 1035 32 | #define IDC_EDIT1 1036 33 | #define IDC_BUTTON3 1037 34 | #define IDC_COMBO1 1038 35 | #define IDC_BUTTON4 1039 36 | #define IDD_DIALOG4 1040 37 | #define IDC_BUTTON5 1041 38 | #define IDC_BUTTON6 1042 39 | #define IDC_BUTTON7 1043 40 | #define IDC_BUTTON8 1044 41 | #define IDC_BUTTON9 1045 42 | #define IDR_BUTTON1 1046 43 | #define IDR_BUTTON2 1047 44 | #define IDC_BUTTON10 1048 45 | #define IDC_BUTTON11 1049 46 | #define IDD_DIALOG5 1050 47 | #define IDD_DIALOG6 1051 48 | #define IDC_PRESS_KEY 1052 49 | 50 | // Next default values for new objects 51 | // 52 | #ifdef APSTUDIO_INVOKED 53 | #ifndef APSTUDIO_READONLY_SYMBOLS 54 | #define _APS_NEXT_RESOURCE_VALUE 116 55 | #define _APS_NEXT_COMMAND_VALUE 40001 56 | #define _APS_NEXT_CONTROL_VALUE 1039 57 | #define _APS_NEXT_SYMED_VALUE 101 58 | #endif 59 | #endif 60 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## NOTE: This repository will soon be deprectated 2 | The random map generation is integrated into the latest builds of ScummVM, which is be the preferred way to play Moonbase Commander online. At the time of writing (July 8th 2024) this has been implemented in the ScummVM [daily builds](https://scummvm.org/downloads/#daily). 3 | 4 | If you would like to find opponents to play against, join the [Moonbase Commander discord server](https://discord.gg/6J8c7XW). 5 | 6 | # INSTRUCTIONS: 7 | - Download MoonbaseConsole.exe from the releases tab 8 | - Place MoonbaseConsole.exe in the same directory as Moonbase.exe and run as administrator. 9 | 10 | # README 11 | 12 | This is the source code to Moonbase Console, a helper program for [Moonbase Commander](http://en.wikipedia.org/wiki/Moonbase_Commander "Moonbase Commander") that generates random maps with particular parameters, and allows easy set-up of multiplayer matches via TCP/IP. 13 | 14 | I (Michael Barlow) didn't write the majority of this code. The code was given to me by Ernie Anderson (MYCROFT), and I originally added this file and the MIT license, and uploaded it to github. I've since added a few more minor changes. 15 | 16 | Usage instructions are located in Moonbase Console\README.TXT. You will need to open the following ports to play multiplayer matches: 17 | 18 | - 2300 (TCP) 19 | - 2350 (UDP) 20 | - 47624 (TCP) 21 | 22 | Thanks Jason Creighton for posting this information on your [blog post](http://jcreigh.blogspot.com.au/2009/04/ports-to-forward-to-host-moonbase.html "blog post") 23 | 24 | # CREDITS 25 | 26 | The following is taken from the "About" dialog within the application. 27 | 28 | > A lot of people helped in one way or the other. Here are the main contributors (in alphabetical order) 29 | 30 | > Katton designed and coded the Katton map generation algorithm. He decoded a lot of the tiles and published what he learned. He also coded the algorithm that puts the "craters" on the map and wrote the code that generates the map preview showing the options. 31 | 32 | > MYCROFT wrote the tools to rip apart the MAP files so they could be deciphered, decoded the rest of the tiles, defined the format that allows the generators to describe the map without caring about tiles, wrote the code to translate the generator output to a useable map, and did the Windows coding. 33 | 34 | > SpacemanSpiff designed and coded the Spiff map generation algorithm. He also contributed to deciphering the map file format. 35 | 36 | > Special thanks to Bwappo for his contest-winning thumbnail image. 37 | 38 | > A number of other people on the Moonbase Commander forums also contributed to map decoding or beta testing including Bwappo, Covak, florent28, Kamolas, llangford, and YorkdinK. 39 | -------------------------------------------------------------------------------- /MoonbaseConsole/MoonbaseConsole.plg: -------------------------------------------------------------------------------- 1 | 2 | 3 |
 4 | 

Build Log

5 |

6 | --------------------Configuration: MoonbaseConsole - Win32 Release-------------------- 7 |

8 |

Command Lines

9 | Creating command line "rc.exe /l 0x409 /fo"Release/MoonbaseConsole.res" /d "NDEBUG" "C:\Documents and Settings\EJANDERSON\Desktop\MyProjects\MoonbaseConsole\MoonbaseConsole.rc"" 10 | Creating temporary file "C:\DOCUME~1\EJANDE~1\LOCALS~1\Temp\RSP41.tmp" with contents 11 | [ 12 | /nologo /ML /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "MOONBASECONSOLE" /Fo"Release/" /Fd"Release/" /FD /c 13 | "C:\Documents and Settings\EJANDERSON\Desktop\MyProjects\MoonbaseConsole\Base64Encode.cpp" 14 | "C:\Documents and Settings\EJANDERSON\Desktop\MyProjects\MoonbaseConsole\crc.cpp" 15 | "C:\Documents and Settings\EJANDERSON\Desktop\MyProjects\MoonbaseConsole\KattonGen.cpp" 16 | "C:\Documents and Settings\EJANDERSON\Desktop\MyProjects\Common\mbcmif.cpp" 17 | "C:\Documents and Settings\EJANDERSON\Desktop\MyProjects\MoonbaseConsole\MoonbaseConsole.cpp" 18 | "C:\Documents and Settings\EJANDERSON\Desktop\MyProjects\MoonbaseConsole\SpiffGen.cpp" 19 | ] 20 | Creating command line "cl.exe @C:\DOCUME~1\EJANDE~1\LOCALS~1\Temp\RSP41.tmp" 21 | Creating temporary file "C:\DOCUME~1\EJANDE~1\LOCALS~1\Temp\RSP42.tmp" with contents 22 | [ 23 | /nologo /ML /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "MOONBASECONSOLE" /Fp"Release/MoonbaseConsole.pch" /Yc"stdafx.h" /Fo"Release/" /Fd"Release/" /FD /c 24 | "C:\Documents and Settings\EJANDERSON\Desktop\MyProjects\MoonbaseConsole\StdAfx.cpp" 25 | ] 26 | Creating command line "cl.exe @C:\DOCUME~1\EJANDE~1\LOCALS~1\Temp\RSP42.tmp" 27 | Creating temporary file "C:\DOCUME~1\EJANDE~1\LOCALS~1\Temp\RSP43.tmp" with contents 28 | [ 29 | kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib wininet.lib ws2_32.lib /nologo /subsystem:windows /incremental:no /pdb:"Release/MoonbaseConsole.pdb" /machine:I386 /out:"Release/MoonbaseConsole.exe" 30 | ".\Release\Base64Encode.obj" 31 | ".\Release\crc.obj" 32 | ".\Release\KattonGen.obj" 33 | ".\Release\mbcmif.obj" 34 | ".\Release\MoonbaseConsole.obj" 35 | ".\Release\SpiffGen.obj" 36 | ".\Release\StdAfx.obj" 37 | ".\Release\MoonbaseConsole.res" 38 | ] 39 | Creating command line "link.exe @C:\DOCUME~1\EJANDE~1\LOCALS~1\Temp\RSP43.tmp" 40 |

Output Window

41 | Compiling resources... 42 | Compiling... 43 | StdAfx.cpp 44 | Compiling... 45 | Base64Encode.cpp 46 | crc.cpp 47 | KattonGen.cpp 48 | mbcmif.cpp 49 | MoonbaseConsole.cpp 50 | SpiffGen.cpp 51 | Generating Code... 52 | Linking... 53 | 54 | 55 | 56 |

Results

57 | MoonbaseConsole.exe - 0 error(s), 0 warning(s) 58 |
59 | 60 | 61 | -------------------------------------------------------------------------------- /MoonbaseConsole/Base64Encode.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "crc.h" 4 | 5 | 6 | 7 | char szBase64EncodeTableG[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+-"; 8 | 9 | unsigned char Base64CharToValue (char ch) 10 | { 11 | if (ch >= '0' && ch <= '9') 12 | return ch - '0'; 13 | else if (ch >= 'a' && ch <= 'z') 14 | return ch - 'a' + 10; 15 | else if (ch >= 'A' && ch <= 'Z') 16 | return ch - 'A' + 36; 17 | else if ('+' == ch) 18 | return 62; 19 | else 20 | return 63; 21 | } 22 | 23 | unsigned int Base64Len (int len) 24 | { 25 | len *= 4; 26 | return len / 3 + ((len % 3) > 0); 27 | } 28 | 29 | void SecureBase64Encode (unsigned char *pby, int cby, char *psz, int cbszMax) 30 | { 31 | //assert(cbszMax >= (((cby + 1) * 4) / 3); 32 | 33 | unsigned char *pb = (unsigned char *)calloc(cby + 1 + 1, 1); // data plus crc plus blank byte (to simplify encoding) 34 | memcpy(pb, pby, cby); 35 | pb[cby] = crc8(pby, cby); 36 | 37 | int c = Base64Len(cby + 1); 38 | int i; 39 | int iby = 0; 40 | for (i = 0; i < c; ++i) 41 | { 42 | switch (i % 4) 43 | { 44 | case 0: 45 | psz[i] = szBase64EncodeTableG[pb[iby] >> 2]; // First character is the leftmost 6 bits, leaving 2 46 | break; 47 | case 1: 48 | psz[i] = szBase64EncodeTableG[((pb[iby] & 0x03) << 4) | (pb[iby + 1] >> 4)]; // Second is remaining 2 lsb plus 4 msb of next 49 | iby++; 50 | break; 51 | case 2: 52 | psz[i] = szBase64EncodeTableG[((pb[iby] & 0x0F) << 2) | (pb[iby + 1] >> 6)]; // Third is remaing 4 lsb plus 2 msb of next 53 | iby++; 54 | break; 55 | case 3: 56 | psz[i] = szBase64EncodeTableG[pb[iby] & 0x3F]; // Fourth is remaining 6 lsb 57 | iby++; 58 | break; 59 | } 60 | } 61 | 62 | psz[i] = '\0'; 63 | 64 | free(pb); 65 | 66 | return; 67 | } 68 | 69 | bool SecureBase64Decode (unsigned char *pby, int cby, char *psz) 70 | { 71 | if (Base64Len(cby + 1) != strlen(psz)) 72 | return false; 73 | 74 | unsigned char *pb = (unsigned char *)calloc(strlen(psz), 1); // This is longer than we need, but better than a boundary condition error. 75 | 76 | int iby = 0; 77 | for (unsigned int i = 0; i < strlen(psz); ++i) 78 | { 79 | unsigned char nVal = Base64CharToValue(psz[i]); 80 | 81 | switch (i % 4) 82 | { 83 | case 0: 84 | pb[iby] = nVal << 2; 85 | break; 86 | case 1: 87 | pb[iby] |= (nVal & 0x30) >> 4; 88 | iby++; 89 | pb[iby] = (nVal & 0x0F) << 4; 90 | break; 91 | case 2: 92 | pb[iby] |= (nVal & 0x3C) >> 2; 93 | iby++; 94 | pb[iby] = (nVal & 0x03) << 6; 95 | break; 96 | case 3: 97 | pb[iby] |= nVal; 98 | iby++; 99 | break; 100 | } 101 | } 102 | 103 | bool bRet = (crc8(pb, iby - 1) == pb[iby - 1]); 104 | 105 | memcpy(pby, pb, iby - 1); 106 | 107 | free(pb); 108 | 109 | return bRet; 110 | } -------------------------------------------------------------------------------- /Common/mbcmif.h: -------------------------------------------------------------------------------- 1 | #ifndef __MBCMIF_H__ 2 | #define __MBCMIF_H__ 3 | 4 | 5 | 6 | #include "MBCMapImage.h" 7 | #include 8 | 9 | 10 | 11 | struct MBCMIF 12 | { 13 | int nVersion; 14 | int nDimension; // 32 (small), 40 (medium), 48 (large), 56 (huge), 64 (SAI) 15 | int nTileset; 16 | char szName[17]; 17 | BYTE aaCornerMap[MAX_TILE_COUNT][MAX_TILE_COUNT]; 18 | char aaCenterMap[MAX_TILE_COUNT][MAX_TILE_COUNT]; 19 | 20 | MBCMIF (); 21 | void GenerateMap(MBCMapImage& mi); 22 | //void BuildCalibrationMap(void); 23 | #ifndef MOONBASECONSOLE 24 | void Read_MIF_File (FILE *pf); 25 | #endif 26 | void DefineStartLocations (MBCMapImage& mi); 27 | void DefineEnergyPools (MBCMapImage& mi); 28 | void MakeCraters(MBCMapImage& mi); 29 | WORD FindTileFor (int x, int y); 30 | 31 | inline char TLCenter (int x, int y) { return aaCenterMap[(0 == x) ? nDimension - 1 : x - 1][(0 == y) ? nDimension - 1 : y - 1]; } 32 | inline char TCenter (int x, int y) { return aaCenterMap[x] [(0 == y) ? nDimension - 1 : y - 1]; } 33 | inline char TRCenter (int x, int y) { return aaCenterMap[(x + 1) % nDimension] [(0 == y) ? nDimension - 1 : y - 1]; } 34 | inline char LCenter (int x, int y) { return aaCenterMap[(0 == x) ? nDimension - 1 : x - 1][y]; } 35 | inline char RCenter (int x, int y) { return aaCenterMap[(x + 1) % nDimension] [y]; } 36 | inline char BLCenter (int x, int y) { return aaCenterMap[(0 == x) ? nDimension - 1 : x - 1][(y + 1) % nDimension]; } 37 | inline char BCenter (int x, int y) { return aaCenterMap[x] [(y + 1) % nDimension]; } 38 | inline char BRCenter (int x, int y) { return aaCenterMap[(x + 1) % nDimension] [(y + 1) % nDimension]; } 39 | 40 | inline BYTE TLCorner (int x, int y) { return aaCornerMap[x][y]; } 41 | inline BYTE TRCorner (int x, int y) { return aaCornerMap[(x + 1) % nDimension][y]; } 42 | inline BYTE BLCorner (int x, int y) { return aaCornerMap[x][(y + 1) % nDimension]; } 43 | inline BYTE BRCorner (int x, int y) { return aaCornerMap[(x + 1) % nDimension][(y + 1) % nDimension]; } 44 | 45 | inline BYTE TTLLCorner (int x, int y) { return TLCorner((x == 0) ? nDimension - 1 : x - 1, (y == 0) ? nDimension - 1: y - 1); } 46 | inline BYTE TTLCorner (int x, int y) { return TRCorner((x == 0) ? nDimension - 1 : x - 1, (y == 0) ? nDimension - 1: y - 1); } 47 | inline BYTE TTRCorner (int x, int y) { return TLCorner((x + 1) % nDimension, (y == 0) ? nDimension - 1: y - 1); } 48 | inline BYTE TTRRCorner (int x, int y) { return TRCorner((x + 1) % nDimension, (y == 0) ? nDimension - 1: y - 1); } 49 | inline BYTE TLLCorner (int x, int y) { return TLCorner((x == 0) ? nDimension - 1 : x - 1, y); } 50 | inline BYTE TRRCorner (int x, int y) { return TRCorner((x + 1) % nDimension, y); } 51 | inline BYTE BLLCorner (int x, int y) { return BLCorner((x == 0) ? nDimension - 1 : x - 1, y); } 52 | inline BYTE BRRCorner (int x, int y) { return BRCorner((x + 1) % nDimension, y); } 53 | inline BYTE BBLLCorner (int x, int y) { return BLCorner((x == 0) ? nDimension - 1 : x - 1, (y + 1) % nDimension); } 54 | inline BYTE BBLCorner (int x, int y) { return BRCorner((x == 0) ? nDimension - 1 : x - 1, (y + 1) % nDimension); } 55 | inline BYTE BBRCorner (int x, int y) { return BLCorner((x + 1) % nDimension, (y + 1) % nDimension); } 56 | inline BYTE BBRRCorner (int x, int y) { return BRCorner((x + 1) % nDimension, (y + 1) % nDimension); } 57 | }; 58 | 59 | 60 | 61 | #endif -------------------------------------------------------------------------------- /MoonbaseConsole/README.TXT: -------------------------------------------------------------------------------- 1 | Moonbase Console v2.1 Documentation 2 | =================================== 3 | 4 | What is This? 5 | ------------- 6 | 7 | Moonbase Console is a utility that generates random maps for use with the game Moonbase Commander. 8 | 9 | 10 | 11 | How do I use it? 12 | ---------------- 13 | 14 | Single Player: 15 | 16 | If you would like to play a game against bots, just press the "Single Player" button. Moonbase Commander will start automatically. The random map will be the first one in the list and will be selected for you. Just set the other game options however you like and play as you would normally. 17 | 18 | 19 | Multiplayer: 20 | 21 | If you would like to play a game against other people, you need to decide who will host the game. 22 | 23 | If you're the host, press the "Host" button. You need to enter your IP address in the "IP Address" field and then press the "Host" button. (If you don't know your IP address, there are some buttons to help you.) A prompt will appear explaining that a game number has been placed on the clipboard. Paste the game number into a message to your opponents using a chat program or an email and send it to them. Once you have done this, press OK on the prompt and Moonbase Commander will start automatically. The random map will be the first one in the list and will be selected for you. Wait for your opponents to join, set all your options the way you like and start the game. 24 | 25 | If someone else is the host, get a game number from them and press the "Join" button. The game number must be exactly right, so you should probably copy and paste it instead of trying to type it. If you get any part of the game number wrong, you won't be able to proceed. Paste the game number into the "Game Number" field and press the "Join" button. Moonbase Commander will start automatically. 26 | 27 | 28 | Random Map Options: 29 | 30 | If you are hosting a game or playing a single player game you can control the parameters of the random map. Change the generation algorithm to choose the personality of the map. Set the size of the map to control the length of the game as well as how soon you'll see action. The tileset doesn't affect gameplay, just the graphics used to draw the map. Move the sliders to change the roughness of the terrain, amount of water, and amount of energy on the map. If you want, you can have the parameters selected randomly by clicking the "Random" checkbox under each parameter. If you do this, the most extreme values of the energy, water, and terrain parameters won't be chosen. 31 | 32 | 33 | 34 | Troubleshooting 35 | --------------- 36 | 37 | "I tried to play multiplayer, but I can't connect" 38 | 39 | First make sure that you can play a normal multiplayer game without Moonbase Console. Then make sure that you're using the right IP address. Moonbase Console doesn't actually do any networking, so if you can play a normal networked game of Moonbase Commander you should be able to use Moonbase Console. 40 | 41 | If you can't get a normal game of Moonbase Commander to work, make sure you have the latest version (1.1 was the newest when this document was written). You may also have trouble with a piece of networking technology called a firewall. Check the forums at http://www.strategyplanet.com/mbc for help. 42 | 43 | 44 | "I want to have two people on my internet connection play at the same time against other people on the internet" 45 | 46 | You can't. This has nothing to do with Moonbase Console, Moonbase Commander was not written to allow this. 47 | 48 | 49 | 50 | Questions and Answers 51 | --------------------- 52 | 53 | * I know what small, medium, large, and huge maps are but what is a SAI, Ridiculous, or MAX map? 54 | 55 | Map sizes are measured in multiples of 8. A small map is 32x32, medium is 40x40, large is 48x48, and huge is 56x56. SAI is one of the built-in maps (one of the better multiplayer ones). Interestingly enough it is 64x64, which is a size that can't be made in the map editor. 56 | 57 | A Ridiculous map is 72x72 and a MAX map is 80x80. These maps are non-standard. They will crash Moonbase Commander if you load them in the map editor, and the minimap doesn't work perfectly with them (the rectangle doesn't show up). Because of this, if you pick a "Random" size map these two will never be picked. 58 | 59 | * What is a Katton map or a SpacemanSpiff map? 60 | 61 | These are the GameSpy handles of the people who developed these different map generation algorithms (see the credits at the end). Each has its own "feel", you should play both to see which one you prefer. Katton maps have no intentional symmetry and never create large energy pools. SpacemanSpiff maps usually have one of several types of symmetry and create all types of energy. 62 | 63 | * When I start a single player game, Moonbase Console starts up talking about an internet connection! 64 | 65 | Moonbase Console actually handles single player games as multiplayer games with no opponents. Don't worry about it, it was easier to implement that way. 66 | 67 | * Do replays work with random maps? 68 | 69 | Yes. Make sure that if you give a replay to someone else you also give them the .map file that goes with it. 70 | 71 | * Where can I find a copy of Moonbase Commander? 72 | 73 | The game can generally only be found in the bargain bin, or on EBay at this point. 74 | 75 | * I got the random maps working fine, but when I play online I lost so badly it wasn't even fun! 76 | 77 | Like lots of online games, the level of play has refined quite a bit over time. You should practice againts bots first, if you can't beat them you don't stand a chance online. You should also check the forums at http://www.strategyplanet.com/mbc for tips. Finally there is a collection of replays at http://www.mbc-rankings.com that you can watch. This is a great way to learn the tricks of the masters! 78 | -------------------------------------------------------------------------------- /MC_README.TXT: -------------------------------------------------------------------------------- 1 | Moonbase Console v2.1 Documentation 2 | =================================== 3 | 4 | What is This? 5 | ------------- 6 | 7 | Moonbase Console is a utility that generates random maps for use with the game Moonbase Commander. 8 | 9 | 10 | 11 | How do I use it? 12 | ---------------- 13 | 14 | Single Player: 15 | 16 | If you would like to play a game against bots, just press the "Single Player" button. Moonbase Commander will start automatically. The random map will be the first one in the list and will be selected for you. Just set the other game options however you like and play as you would normally. 17 | 18 | 19 | Multiplayer: 20 | 21 | If you would like to play a game against other people, you need to decide who will host the game. 22 | 23 | If you're the host, press the "Host" button. You need to enter your IP address in the "IP Address" field and then press the "Host" button. (If you don't know your IP address, there are some buttons to help you.) A prompt will appear explaining that a game number has been placed on the clipboard. Paste the game number into a message to your opponents using a chat program or an email and send it to them. Once you have done this, press OK on the prompt and Moonbase Commander will start automatically. The random map will be the first one in the list and will be selected for you. Wait for your opponents to join, set all your options the way you like and start the game. 24 | 25 | If someone else is the host, get a game number from them and press the "Join" button. The game number must be exactly right, so you should probably copy and paste it instead of trying to type it. If you get any part of the game number wrong, you won't be able to proceed. Paste the game number into the "Game Number" field and press the "Join" button. Moonbase Commander will start automatically. 26 | 27 | 28 | Random Map Options: 29 | 30 | If you are hosting a game or playing a single player game you can control the parameters of the random map. Change the generation algorithm to choose the personality of the map. Set the size of the map to control the length of the game as well as how soon you'll see action. The tileset doesn't affect gameplay, just the graphics used to draw the map. Move the sliders to change the roughness of the terrain, amount of water, and amount of energy on the map. If you want, you can have the parameters selected randomly by clicking the "Random" checkbox under each parameter. If you do this, the most extreme values of the energy, water, and terrain parameters won't be chosen. 31 | 32 | 33 | 34 | Troubleshooting 35 | --------------- 36 | 37 | "I tried to play multiplayer, but I can't connect" 38 | 39 | First make sure that you can play a normal multiplayer game without Moonbase Console. Then make sure that you're using the right IP address. Moonbase Console doesn't actually do any networking, so if you can play a normal networked game of Moonbase Commander you should be able to use Moonbase Console. 40 | 41 | If you can't get a normal game of Moonbase Commander to work, make sure you have the latest version (1.1 was the newest when this document was written). You may also have trouble with a piece of networking technology called a firewall. Check the forums at http://www.strategyplanet.com/mbc for help. 42 | 43 | 44 | "I want to have two people on my internet connection play at the same time against other people on the internet" 45 | 46 | You can't. This has nothing to do with Moonbase Console, Moonbase Commander was not written to allow this. 47 | 48 | 49 | 50 | Questions and Answers 51 | --------------------- 52 | 53 | * I know what small, medium, large, and huge maps are but what is a SAI, Ridiculous, or MAX map? 54 | 55 | Map sizes are measured in multiples of 8. A small map is 32x32, medium is 40x40, large is 48x48, and huge is 56x56. SAI is one of the built-in maps (one of the better multiplayer ones). Interestingly enough it is 64x64, which is a size that can't be made in the map editor. 56 | 57 | A Ridiculous map is 72x72 and a MAX map is 80x80. These maps are non-standard. They will crash Moonbase Commander if you load them in the map editor, and the minimap doesn't work perfectly with them (the rectangle doesn't show up). Because of this, if you pick a "Random" size map these two will never be picked. 58 | 59 | * What is a Katton map or a SpacemanSpiff map? 60 | 61 | These are the GameSpy handles of the people who developed these different map generation algorithms (see the credits at the end). Each has its own "feel", you should play both to see which one you prefer. Katton maps have no intentional symmetry and never create large energy pools. SpacemanSpiff maps usually have one of several types of symmetry and create all types of energy. 62 | 63 | * When I start a single player game, Moonbase Console starts up talking about an internet connection! 64 | 65 | Moonbase Console actually handles single player games as multiplayer games with no opponents. Don't worry about it, it was easier to implement that way. 66 | 67 | * Do replays work with random maps? 68 | 69 | Yes. Make sure that if you give a replay to someone else you also give them the .map file that goes with it. 70 | 71 | * Where can I find a copy of Moonbase Commander? 72 | 73 | The game can generally only be found in the bargain bin, or on EBay at this point. 74 | 75 | * I got the random maps working fine, but when I play online I lost so badly it wasn't even fun! 76 | 77 | Like lots of online games, the level of play has refined quite a bit over time. You should practice againts bots first, if you can't beat them you don't stand a chance online. You should also check the forums at http://www.strategyplanet.com/mbc for tips. Finally there is a collection of replays at http://www.mbc-rankings.com that you can watch. This is a great way to learn the tricks of the masters! 78 | -------------------------------------------------------------------------------- /MoonbaseConsole/MoonbaseConsole.dsp: -------------------------------------------------------------------------------- 1 | # Microsoft Developer Studio Project File - Name="MoonbaseConsole" - Package Owner=<4> 2 | # Microsoft Developer Studio Generated Build File, Format Version 6.00 3 | # ** DO NOT EDIT ** 4 | 5 | # TARGTYPE "Win32 (x86) Application" 0x0101 6 | 7 | CFG=MoonbaseConsole - Win32 Debug 8 | !MESSAGE This is not a valid makefile. To build this project using NMAKE, 9 | !MESSAGE use the Export Makefile command and run 10 | !MESSAGE 11 | !MESSAGE NMAKE /f "MoonbaseConsole.mak". 12 | !MESSAGE 13 | !MESSAGE You can specify a configuration when running NMAKE 14 | !MESSAGE by defining the macro CFG on the command line. For example: 15 | !MESSAGE 16 | !MESSAGE NMAKE /f "MoonbaseConsole.mak" CFG="MoonbaseConsole - Win32 Debug" 17 | !MESSAGE 18 | !MESSAGE Possible choices for configuration are: 19 | !MESSAGE 20 | !MESSAGE "MoonbaseConsole - Win32 Release" (based on "Win32 (x86) Application") 21 | !MESSAGE "MoonbaseConsole - Win32 Debug" (based on "Win32 (x86) Application") 22 | !MESSAGE 23 | 24 | # Begin Project 25 | # PROP AllowPerConfigDependencies 0 26 | # PROP Scc_ProjName "" 27 | # PROP Scc_LocalPath "" 28 | CPP=cl.exe 29 | MTL=midl.exe 30 | RSC=rc.exe 31 | 32 | !IF "$(CFG)" == "MoonbaseConsole - Win32 Release" 33 | 34 | # PROP BASE Use_MFC 0 35 | # PROP BASE Use_Debug_Libraries 0 36 | # PROP BASE Output_Dir "Release" 37 | # PROP BASE Intermediate_Dir "Release" 38 | # PROP BASE Target_Dir "" 39 | # PROP Use_MFC 0 40 | # PROP Use_Debug_Libraries 0 41 | # PROP Output_Dir "Release" 42 | # PROP Intermediate_Dir "Release" 43 | # PROP Ignore_Export_Lib 0 44 | # PROP Target_Dir "" 45 | # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /c 46 | # ADD CPP /nologo /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "MOONBASECONSOLE" /FD /c 47 | # SUBTRACT CPP /YX /Yc /Yu 48 | # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 49 | # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 50 | # ADD BASE RSC /l 0x409 /d "NDEBUG" 51 | # ADD RSC /l 0x409 /d "NDEBUG" 52 | BSC32=bscmake.exe 53 | # ADD BASE BSC32 /nologo 54 | # ADD BSC32 /nologo 55 | LINK32=link.exe 56 | # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 57 | # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib wininet.lib ws2_32.lib /nologo /subsystem:windows /machine:I386 58 | 59 | !ELSEIF "$(CFG)" == "MoonbaseConsole - Win32 Debug" 60 | 61 | # PROP BASE Use_MFC 0 62 | # PROP BASE Use_Debug_Libraries 1 63 | # PROP BASE Output_Dir "Debug" 64 | # PROP BASE Intermediate_Dir "Debug" 65 | # PROP BASE Target_Dir "" 66 | # PROP Use_MFC 0 67 | # PROP Use_Debug_Libraries 1 68 | # PROP Output_Dir "Debug" 69 | # PROP Intermediate_Dir "Debug" 70 | # PROP Ignore_Export_Lib 0 71 | # PROP Target_Dir "" 72 | # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c 73 | # ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "MOONBASECONSOLE" /FD /GZ /c 74 | # SUBTRACT CPP /YX /Yc /Yu 75 | # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 76 | # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 77 | # ADD BASE RSC /l 0x409 /d "_DEBUG" 78 | # ADD RSC /l 0x409 /d "_DEBUG" 79 | BSC32=bscmake.exe 80 | # ADD BASE BSC32 /nologo 81 | # ADD BSC32 /nologo 82 | LINK32=link.exe 83 | # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept 84 | # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib wininet.lib ws2_32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept 85 | 86 | !ENDIF 87 | 88 | # Begin Target 89 | 90 | # Name "MoonbaseConsole - Win32 Release" 91 | # Name "MoonbaseConsole - Win32 Debug" 92 | # Begin Group "Source Files" 93 | 94 | # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" 95 | # Begin Source File 96 | 97 | SOURCE=.\Base64Encode.cpp 98 | # End Source File 99 | # Begin Source File 100 | 101 | SOURCE=.\crc.cpp 102 | # End Source File 103 | # Begin Source File 104 | 105 | SOURCE=.\KattonGen.cpp 106 | # End Source File 107 | # Begin Source File 108 | 109 | SOURCE=..\Common\mbcmif.cpp 110 | # End Source File 111 | # Begin Source File 112 | 113 | SOURCE=.\MoonbaseConsole.cpp 114 | # End Source File 115 | # Begin Source File 116 | 117 | SOURCE=.\SpiffGen.cpp 118 | # End Source File 119 | # Begin Source File 120 | 121 | SOURCE=.\StdAfx.cpp 122 | # ADD CPP /Yc"stdafx.h" 123 | # End Source File 124 | # End Group 125 | # Begin Group "Header Files" 126 | 127 | # PROP Default_Filter "h;hpp;hxx;hm;inl" 128 | # Begin Source File 129 | 130 | SOURCE=.\Base64Encode.h 131 | # End Source File 132 | # Begin Source File 133 | 134 | SOURCE=.\crc.h 135 | # End Source File 136 | # Begin Source File 137 | 138 | SOURCE=.\GameInfo.h 139 | # End Source File 140 | # Begin Source File 141 | 142 | SOURCE=.\KattonGen.h 143 | # End Source File 144 | # Begin Source File 145 | 146 | SOURCE=.\resource.h 147 | # End Source File 148 | # Begin Source File 149 | 150 | SOURCE=.\SpiffGen.h 151 | # End Source File 152 | # Begin Source File 153 | 154 | SOURCE=.\StdAfx.h 155 | # End Source File 156 | # End Group 157 | # Begin Group "Resource Files" 158 | 159 | # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" 160 | # Begin Source File 161 | 162 | SOURCE=.\bitmap1.bmp 163 | # End Source File 164 | # Begin Source File 165 | 166 | SOURCE=.\icon1.ico 167 | # End Source File 168 | # Begin Source File 169 | 170 | SOURCE=.\MoonbaseConsole.rc 171 | # End Source File 172 | # End Group 173 | # Begin Source File 174 | 175 | SOURCE=.\ReadMe.txt 176 | # End Source File 177 | # Begin Source File 178 | 179 | SOURCE=.\Template.thm 180 | # End Source File 181 | # Begin Source File 182 | 183 | SOURCE=.\Template.wiz 184 | # End Source File 185 | # End Target 186 | # End Project 187 | -------------------------------------------------------------------------------- /MoonbaseConsole/MoonbaseConsole.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 13 | 14 | 15 | 16 | 17 | 27 | 30 | 33 | 36 | 39 | 48 | 63 | 66 | 71 | 74 | 86 | 89 | 92 | 95 | 100 | 103 | 106 | 109 | 110 | 120 | 123 | 126 | 129 | 132 | 141 | 156 | 159 | 164 | 167 | 180 | 183 | 186 | 189 | 194 | 197 | 200 | 203 | 204 | 205 | 206 | 207 | 208 | 212 | 215 | 218 | 222 | 223 | 226 | 230 | 231 | 232 | 235 | 238 | 242 | 243 | 246 | 250 | 251 | 252 | 255 | 258 | 262 | 263 | 266 | 270 | 271 | 272 | 275 | 278 | 282 | 283 | 286 | 290 | 291 | 292 | 295 | 298 | 302 | 303 | 306 | 310 | 311 | 312 | 315 | 318 | 322 | 323 | 326 | 330 | 331 | 332 | 335 | 338 | 344 | 345 | 348 | 354 | 355 | 356 | 357 | 361 | 364 | 365 | 368 | 369 | 372 | 373 | 376 | 377 | 380 | 381 | 384 | 385 | 388 | 389 | 390 | 394 | 397 | 398 | 401 | 402 | 405 | 408 | 412 | 413 | 416 | 420 | 421 | 422 | 423 | 426 | 427 | 430 | 431 | 434 | 435 | 436 | 437 | 438 | 439 | -------------------------------------------------------------------------------- /MoonbaseConsole/MoonbaseConsole.rc: -------------------------------------------------------------------------------- 1 | //Microsoft Developer Studio generated resource script. 2 | // 3 | #include "resource.h" 4 | 5 | #define APSTUDIO_READONLY_SYMBOLS 6 | ///////////////////////////////////////////////////////////////////////////// 7 | // 8 | // Generated from the TEXTINCLUDE 2 resource. 9 | // 10 | //#include "afxres.h" 11 | #include "winresrc.h" 12 | #define IDC_STATIC -1 13 | 14 | ///////////////////////////////////////////////////////////////////////////// 15 | #undef APSTUDIO_READONLY_SYMBOLS 16 | 17 | ///////////////////////////////////////////////////////////////////////////// 18 | // English (U.S.) resources 19 | 20 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) 21 | #ifdef _WIN32 22 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US 23 | #pragma code_page(1252) 24 | #endif //_WIN32 25 | 26 | ///////////////////////////////////////////////////////////////////////////// 27 | // 28 | // Main Dialog 29 | // 30 | 31 | IDD_DIALOG1 DIALOG DISCARDABLE 0, 0, 337, 238 32 | STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU 33 | CAPTION "Moonbase Console v2.2" 34 | FONT 8, "MS Sans Serif" 35 | BEGIN 36 | PUSHBUTTON "&Join",IDC_BUTTON2,5,5,105,15 37 | PUSHBUTTON "&Host",IDC_BTN_HOST_GAME,115,5,105,15 38 | PUSHBUTTON "&Single Player",IDC_SINGLE_GENERATE,225,5,105,15, 39 | BS_MULTILINE 40 | CONTROL "Slider1",IDC_SLIDER2,"msctls_trackbar32",TBS_VERT | 41 | WS_TABSTOP,10,43,20,105 42 | CONTROL "Random",IDC_CHECK2,"Button",BS_AUTOCHECKBOX | 43 | WS_TABSTOP,15,150,43,10 44 | CONTROL "Slider1",IDC_SLIDER1,"msctls_trackbar32",TBS_AUTOTICKS | 45 | TBS_VERT | WS_TABSTOP,55,43,20,105 46 | CONTROL "Random",IDC_CHECK1,"Button",BS_AUTOCHECKBOX | 47 | WS_TABSTOP,63,151,43,10 48 | CONTROL "Slider1",IDC_SLIDER6,"msctls_trackbar32",TBS_AUTOTICKS | 49 | TBS_VERT | WS_TABSTOP,111,43,20,105 50 | CONTROL "Random",IDC_CHECK6,"Button",BS_AUTOCHECKBOX | 51 | WS_TABSTOP,119,151,43,10 52 | CONTROL "Slider1",IDC_SLIDER3,"msctls_trackbar32",TBS_AUTOTICKS | 53 | TBS_VERT | WS_TABSTOP,165,43,20,105 54 | CONTROL "Random",IDC_CHECK3,"Button",BS_AUTOCHECKBOX | 55 | WS_TABSTOP,173,151,43,10 56 | CONTROL "Slider1",IDC_SLIDER4,"msctls_trackbar32",TBS_AUTOTICKS | 57 | TBS_VERT | WS_TABSTOP,221,43,20,105 58 | CONTROL "Random",IDC_CHECK4,"Button",BS_AUTOCHECKBOX | 59 | WS_TABSTOP,229,151,43,10 60 | CONTROL "Slider1",IDC_SLIDER5,"msctls_trackbar32",TBS_AUTOTICKS | 61 | TBS_VERT | WS_TABSTOP,275,43,20,105 62 | CONTROL "Random",IDC_CHECK5,"Button",BS_AUTOCHECKBOX | 63 | WS_TABSTOP,283,151,42,10 64 | GROUPBOX "Random Map Options",IDC_STATIC,5,25,325,140 65 | LTEXT "Small",IDC_STATIC,75,47,18,8 66 | LTEXT "Medium",IDC_STATIC,75,62,26,8 67 | LTEXT "Large",IDC_STATIC,75,76,19,8 68 | LTEXT "Huge",IDC_STATIC,75,91,18,8 69 | LTEXT "SAI",IDC_STATIC,75,106,12,8 70 | LTEXT "Ridiculous",IDC_STATIC,75,121,34,8 71 | LTEXT "Max",IDC_STATIC,75,136,14,8 72 | LTEXT "Size",IDC_STATIC,55,35,14,8 73 | LTEXT "Energy",IDC_STATIC,165,35,23,8 74 | LTEXT "Terrain",IDC_STATIC,221,35,23,8 75 | LTEXT "Water",IDC_STATIC,275,35,20,8 76 | LTEXT "Spiff",IDC_STATIC,30,47,15,10 77 | LTEXT "Katton",IDC_STATIC,30,136,22,8 78 | LTEXT "Scarce",IDC_STATIC,185,136,24,8 79 | LTEXT "Lots",IDC_STATIC,185,47,14,8 80 | LTEXT "Barren",IDC_STATIC,241,136,22,8 81 | LTEXT "Rough",IDC_STATIC,241,47,22,8 82 | LTEXT "Some",IDC_STATIC,185,91,19,8 83 | LTEXT "Driest",IDC_STATIC,295,136,19,8 84 | LTEXT "Wettest",IDC_STATIC,295,47,26,8 85 | LTEXT "Normal",IDC_STATIC,295,91,23,8 86 | LTEXT "Normal",IDC_STATIC,241,91,23,8 87 | LTEXT "Tileset",IDC_STATIC,111,35,25,8 88 | LTEXT "Terrandra",IDC_STATIC,131,136,32,8 89 | LTEXT "Zanateros",IDC_STATIC,131,118,33,8 90 | LTEXT "Drijim 3",IDC_STATIC,131,100,24,8 91 | LTEXT "Kyanite",IDC_STATIC,131,83,24,8 92 | LTEXT "Emerau Glyph",IDC_STATIC,131,61,29,20 93 | LTEXT "Ablation Laund",IDC_STATIC,131,43,30,16 94 | LTEXT "Algorithm",IDC_STATIC,10,35,30,8 95 | LTEXT "Spiff algorithm is rotationally symmetrical. Katton algorithm is not. RUN THIS AS ADMINISTRATOR",IDC_STATIC,10,173,325,29 96 | GROUPBOX "Game Options",IDC_STATIC,5,185,325,29 97 | PUSHBUTTON "Se&ttings",IDC_BUTTON4,10,195,155,14 98 | PUSHBUTTON "H&elp",IDC_BUTTON1,5,219,160,14 99 | PUSHBUTTON "&Credits",IDC_BUTTON3,170,219,160,14 100 | END 101 | 102 | ///////////////////////////////////////////////////////////////////////////// 103 | // 104 | // Join Game Dialog 105 | // 106 | IDD_DIALOG2 DIALOG DISCARDABLE 0, 0, 186, 46 107 | STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU 108 | CAPTION "Join Game" 109 | FONT 8, "MS Sans Serif" 110 | BEGIN 111 | EDITTEXT IDC_EDIT2,5,20,100,14,ES_AUTOHSCROLL 112 | DEFPUSHBUTTON "Join",IDOK,129,7,50,14 113 | PUSHBUTTON "Cancel",IDCANCEL,129,24,50,14 114 | LTEXT "Game &Number:",IDC_STATIC,5,7,48,8 115 | END 116 | 117 | ///////////////////////////////////////////////////////////////////////////// 118 | // 119 | // Host Game Dialog 120 | // 121 | IDD_DIALOG3 DIALOG DISCARDABLE 0, 0, 237, 201 122 | STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU 123 | CAPTION "Host Game" 124 | FONT 8, "MS Sans Serif" 125 | BEGIN 126 | CONTROL "IPAddress3",IDC_IPADDRESS1,"SysIPAddress32",WS_TABSTOP, 127 | 108,35,81,14 128 | COMBOBOX IDC_COMBO1,5,100,110,105,CBS_DROPDOWN | CBS_SORT | 129 | WS_VSCROLL | WS_TABSTOP 130 | PUSHBUTTON "Detect &Internet Address",IDC_BUTTON1,120,100,110,14 131 | PUSHBUTTON "Detect &LAN Address",IDC_BUTTON3,63,140,110,14 132 | DEFPUSHBUTTON "&Host",IDOK,5,180,110,14 133 | PUSHBUTTON "Cancel",IDCANCEL,120,180,110,14 134 | LTEXT "IP &Address:",IDC_STATIC,68,38,40,10 135 | LTEXT "To host a game, enter your IP address in the box below and press the Host button. If you do not know your IP address, try one of the options below.", 136 | IDC_STATIC,5,5,225,25 137 | LTEXT "If you are playing a game over the internet, pick a detection site from the list below and press the Detect Internet Address button. Note that you will need to forward ports 2300 TCP, 2350 UDP and 47624 TCP to your computer for this to work.", 138 | IDC_STATIC,5,65,225,35 139 | LTEXT "If you are playing a game over a network, press the Detect LAN Address button.", 140 | IDC_STATIC,5,120,225,15 141 | CONTROL "",IDC_STATIC,"Static",SS_BLACKFRAME | SS_SUNKEN,5,165, 142 | 225,1 143 | END 144 | 145 | ///////////////////////////////////////////////////////////////////////////// 146 | // 147 | // Game Options Dialog 148 | // 149 | IDD_DIALOG4 DIALOG DISCARDABLE 0, 0, 280, 220 150 | STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU 151 | CAPTION "Game Options" 152 | FONT 8, "MS Sans Serif" 153 | BEGIN 154 | GROUPBOX "Player Name",IDC_STATIC,5,5,110,39 155 | CTEXT "COMMANDER",IDC_TXT1,10,15,100,10 156 | PUSHBUTTON "&Change",IDC_BUTTON1,60,25,50,14 157 | GROUPBOX "Controls",IDC_STATIC,5,49,110,130 158 | LTEXT "Damage Bar",IDC_STATIC,10,59,80,10 159 | PUSHBUTTON "D",IDC_BUTTON2,65,57,45,12 160 | LTEXT "Range Radius",IDC_STATIC,10,74,80,10 161 | PUSHBUTTON "R",IDC_BUTTON3,65,72,45,12 162 | LTEXT "Center Unit",IDC_STATIC,10,89,80,10 163 | PUSHBUTTON "C",IDC_BUTTON4,65,86,45,12 164 | LTEXT "Next Unit",IDC_STATIC,10,104,80,10 165 | PUSHBUTTON "N",IDC_BUTTON5,65,101,45,12 166 | LTEXT "Previous Unit",IDC_STATIC,10,119,80,10 167 | PUSHBUTTON "P",IDC_BUTTON6,65,116,45,12 168 | LTEXT "Closest Launcher",IDC_STATIC,10,134,80,10 169 | PUSHBUTTON "L",IDC_BUTTON7,65,131,45,12 170 | LTEXT "Show Attacked",IDC_STATIC,10,149,80,10 171 | PUSHBUTTON "A",IDC_BUTTON8,65,146,45,12 172 | LTEXT "Chat Toggle",IDC_STATIC,10,164,80,10 173 | PUSHBUTTON "TAB",IDC_BUTTON9,65,161,45,12 174 | GROUPBOX "Preferences",IDC_STATIC,120,5,155,70 175 | CONTROL "Auto Scroll",IDC_CHECK1,"Button",BS_AUTOCHECKBOX | 176 | WS_TABSTOP,125,15,80,10 177 | CONTROL "Auto Hub Select",IDC_CHECK2,"Button",BS_AUTOCHECKBOX | 178 | WS_TABSTOP,125,30,80,10 179 | CONTROL "Smart Camera",IDC_CHECK3,"Button",BS_AUTOCHECKBOX | 180 | WS_TABSTOP,125,45,80,10 181 | CONTROL "Auto Return Camera",IDC_CHECK4,"Button",BS_AUTOCHECKBOX | 182 | WS_TABSTOP,125,60,80,10 183 | GROUPBOX "Audio",IDC_STATIC,120,80,155,119 184 | LTEXT "SFX vol.",IDC_STATIC,125,90,80,10 185 | CONTROL "Slider1",IDC_SLIDER1,"msctls_trackbar32", WS_TABSTOP,160,90,110,20 186 | LTEXT "Music vol.",IDC_STATIC,125,110,80,10 187 | CONTROL "Slider1",IDC_SLIDER2,"msctls_trackbar32", WS_TABSTOP,160,110,110,20 188 | LTEXT "Voice vol.",IDC_STATIC,125,130,80,10 189 | CONTROL "Slider1",IDC_SLIDER3,"msctls_trackbar32", WS_TABSTOP,160,130,110,20 190 | LTEXT "Interface vol.",IDC_STATIC,125,150,100,10 191 | CONTROL "Slider1",IDC_SLIDER4,"msctls_trackbar32", WS_TABSTOP,160,150,110,20 192 | CONTROL "Commentary",IDC_CHECK5,"Button",BS_AUTOCHECKBOX | 193 | WS_TABSTOP,125,170,100,10 194 | LTEXT "Music Quality",IDC_STATIC,125,185,80,10 195 | CONTROL "Low",IDR_BUTTON1,"Button",BS_AUTORADIOBUTTON | WS_GROUP,180,185,40,10 196 | CONTROL "High",IDR_BUTTON2,"Button", BS_AUTORADIOBUTTON,220,185,40,10 197 | PUSHBUTTON "&Reset",IDC_BUTTON10,5,204,85,14 198 | PUSHBUTTON "&Cancel",IDCANCEL,95,204,85,14 199 | DEFPUSHBUTTON "&OK",IDOK,185,204,85,14 200 | END 201 | 202 | ///////////////////////////////////////////////////////////////////////////// 203 | // 204 | // Change Player Name Dialog 205 | // 206 | IDD_DIALOG5 DIALOG DISCARDABLE 0, 0, 186, 46 207 | STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU 208 | CAPTION "Change Player Name" 209 | FONT 8, "MS Sans Serif" 210 | BEGIN 211 | EDITTEXT IDC_EDIT2,5,20,100,14,ES_AUTOHSCROLL 212 | DEFPUSHBUTTON "&OK",IDOK,129,7,50,14 213 | PUSHBUTTON "Cancel",IDCANCEL,129,24,50,14 214 | LTEXT "Name:",IDC_STATIC,5,7,48,8 215 | END 216 | 217 | ///////////////////////////////////////////////////////////////////////////// 218 | // 219 | // Change Key Dialog 220 | // 221 | IDD_DIALOG6 DIALOG DISCARDABLE 0, 0, 186, 46 222 | STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU 223 | CAPTION "Change Key" 224 | FONT 8, "MS Sans Serif" 225 | BEGIN 226 | CTEXT "Press a key...",IDC_PRESS_KEY,5,7,48,8 227 | END 228 | 229 | ///////////////////////////////////////////////////////////////////////////// 230 | // 231 | // DESIGNINFO 232 | // 233 | 234 | #ifdef APSTUDIO_INVOKED 235 | GUIDELINES DESIGNINFO DISCARDABLE 236 | BEGIN 237 | IDD_DIALOG1, DIALOG 238 | BEGIN 239 | LEFTMARGIN, 7 240 | RIGHTMARGIN, 330 241 | TOPMARGIN, 7 242 | BOTTOMMARGIN, 184 243 | END 244 | 245 | IDD_DIALOG2, DIALOG 246 | BEGIN 247 | LEFTMARGIN, 7 248 | RIGHTMARGIN, 179 249 | TOPMARGIN, 7 250 | BOTTOMMARGIN, 39 251 | END 252 | 253 | IDD_DIALOG3, DIALOG 254 | BEGIN 255 | LEFTMARGIN, 7 256 | RIGHTMARGIN, 230 257 | TOPMARGIN, 7 258 | BOTTOMMARGIN, 194 259 | END 260 | 261 | IDD_DIALOG5, DIALOG 262 | BEGIN 263 | LEFTMARGIN, 7 264 | RIGHTMARGIN, 179 265 | TOPMARGIN, 7 266 | BOTTOMMARGIN, 39 267 | END 268 | END 269 | #endif // APSTUDIO_INVOKED 270 | 271 | 272 | #ifdef APSTUDIO_INVOKED 273 | ///////////////////////////////////////////////////////////////////////////// 274 | // 275 | // TEXTINCLUDE 276 | // 277 | 278 | 1 TEXTINCLUDE DISCARDABLE 279 | BEGIN 280 | "resource.h\0" 281 | END 282 | 283 | 2 TEXTINCLUDE DISCARDABLE 284 | BEGIN 285 | "#include ""afxres.h""\r\n" 286 | "\0" 287 | END 288 | 289 | 3 TEXTINCLUDE DISCARDABLE 290 | BEGIN 291 | "\r\n" 292 | "\0" 293 | END 294 | 295 | #endif // APSTUDIO_INVOKED 296 | 297 | 298 | ///////////////////////////////////////////////////////////////////////////// 299 | // 300 | // Icon 301 | // 302 | 303 | // Icon with lowest ID value placed first to ensure application icon 304 | // remains consistent on all systems. 305 | IDI_ICON1 ICON DISCARDABLE "icon1.ico" 306 | 307 | ///////////////////////////////////////////////////////////////////////////// 308 | // 309 | // WIZ 310 | // 311 | 312 | IDR_WIZ1 WIZ DISCARDABLE "Template.wiz" 313 | 314 | ///////////////////////////////////////////////////////////////////////////// 315 | // 316 | // TXT 317 | // 318 | 319 | IDR_TXT1 TXT DISCARDABLE "README.TXT" 320 | 321 | ///////////////////////////////////////////////////////////////////////////// 322 | // 323 | // THM 324 | // 325 | 326 | IDR_THM1 THM DISCARDABLE "Template.thm" 327 | #endif // English (U.S.) resources 328 | ///////////////////////////////////////////////////////////////////////////// 329 | 330 | 331 | 332 | #ifndef APSTUDIO_INVOKED 333 | ///////////////////////////////////////////////////////////////////////////// 334 | // 335 | // Generated from the TEXTINCLUDE 3 resource. 336 | // 337 | 338 | 339 | ///////////////////////////////////////////////////////////////////////////// 340 | #endif // not APSTUDIO_INVOKED 341 | 342 | -------------------------------------------------------------------------------- /MoonbaseConsole/SpiffGen.cpp: -------------------------------------------------------------------------------- 1 | //MBC mapper by William Myers 2 | 3 | // Revision history: 4 | // 08/08/2003 WNM Initial C++ version 5 | // 08/08/2003 EJA Syntax cleanup and compilation 6 | // 09/03/2003 WNM Rewritten, more start positions added. 7 | // 10/05/2003 WNM Inconsistent result bug hopefully fixed, water input added, 8 | // pool number and size now random based on map size and energy input 9 | 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include "mbcmif.h" 16 | #include "GameInfo.h" 17 | 18 | #define MAXELEVVAL 4 //for array size 19 | #define HIGH 3 //elevations 20 | #define MEDIUM 2 21 | #define LOW 1 22 | #define WATER 0 //special types 23 | #define HUB 1 24 | #define SMALLPOOL 2 25 | #define MEDIUMPOOL 3 26 | #define LARGEPOOLTOP 4 27 | #define LARGEPOOLBOTTOM 5 //placeholder for top half of a large pool 28 | 29 | #define UNASSIGNED -1 30 | #define LOW_OR_WATER -2 31 | 32 | #define MAXSIZE 80 33 | 34 | int numPoolsG; //per quadrant 35 | int energyAmountG; //2048 = min energy on small map, 51200 = max energy on max map, etc. 36 | int cliffAmountG; //amount of cliffs, 10 is min, 70 is max 37 | int waterAmountG; //0 is min, 30 is max 38 | int totalMapSizeG; 39 | 40 | int terrainSeedFlagG; //disables HIGH or LOW terrain for the initial elevation when appropriate 41 | int islandsFlagG; //enables islands 42 | int advancedMirrorOK_G; //low terrain roughness can leave too abrupt changes at the edge, so set false to disable some mirroring types 43 | int mirrorTypeG; //what mirroring is used 44 | #define NORMALMIRROR 0 45 | #define XOFFSETMIRROR 1 46 | #define YOFFSETMIRROR 2 47 | #define MAXDISTMIRROR 3 48 | 49 | int mapCornerMaxG; //size of random section 50 | int mapMiddleMaxG; 51 | int mapCorner[MAXSIZE+1][MAXSIZE+1]; 52 | int mapMiddle[MAXSIZE][MAXSIZE]; 53 | 54 | //void stats(); 55 | 56 | float float_rand() 57 | { 58 | // The rand function returns a pseudorandom integer in the range 0 to RAND_MAX. 59 | return ((float)rand()) / RAND_MAX; 60 | } 61 | 62 | int SpiffRand(int min, int max) //returns a random integer min to max inclusive 63 | { 64 | return ((int)(float_rand() * (max + 1 - min))) + min; 65 | } 66 | 67 | int pickFrom2(int A, int probA, int B, int probB) 68 | { 69 | float R = float_rand() * (probA + probB); 70 | if (R < probA) 71 | return A; 72 | else 73 | return B; 74 | } 75 | 76 | int pickFrom3(int A, int probA, int B, int probB, int C, int probC) 77 | { 78 | float R = float_rand() * (probA + probB + probC); 79 | if (R < probA) 80 | return A; 81 | else if (R < probA + probB) 82 | return B; 83 | else 84 | return C; 85 | } 86 | 87 | int pickFrom4(int A, int probA, int B, int probB, int C, int probC, int D, int probD) 88 | { 89 | float R = float_rand() * (probA + probB + probC + probD); 90 | if (R < probA) 91 | return A; 92 | else if (R < probA + probB) 93 | return B; 94 | else if (R < probA + probB + probC) 95 | return C; 96 | else 97 | return D; 98 | } 99 | 100 | void getSpecials() //choose where the starting points and pools are 101 | { 102 | int x, y, p, t; 103 | int edgeWaterA = (int)(islandsFlagG * totalMapSizeG / 16 + 0.5); 104 | int edgeWaterB = (int)(islandsFlagG * totalMapSizeG / 16); //don't put pools between islands 105 | 106 | // No matter what, they get a start hub spot. 107 | if (mirrorTypeG == MAXDISTMIRROR) 108 | x = (int)((totalMapSizeG*3+8)/16); 109 | else 110 | x = (int)(mapMiddleMaxG/2); 111 | y = x; 112 | 113 | mapMiddle[x][y] = HUB; //hub start position 114 | 115 | for (p = 1; p <= numPoolsG; ++p) 116 | { 117 | x = SpiffRand(edgeWaterA, mapMiddleMaxG-edgeWaterB); 118 | y = SpiffRand(edgeWaterA, mapMiddleMaxG-edgeWaterB); 119 | if (mapMiddle[x][y] != UNASSIGNED) 120 | --p;//repick this pool 121 | else 122 | { 123 | t = pickFrom3(SMALLPOOL,40000*numPoolsG, MEDIUMPOOL,20000*numPoolsG+energyAmountG, LARGEPOOLTOP,2*energyAmountG); 124 | if (t == LARGEPOOLTOP) 125 | if ((y == mapMiddleMaxG-edgeWaterB)||(mapMiddle[x][y+1] != UNASSIGNED)) 126 | t = SMALLPOOL; //keep large pool from being too high or overlapping another pool or start 127 | else 128 | mapMiddle[x][y+1] = LARGEPOOLBOTTOM; 129 | mapMiddle[x][y] = t; 130 | } 131 | } 132 | } 133 | void copyMap(int XOffset, int YOffset, int XDirection, int YDirection) 134 | //copies the first quadrant of the map 135 | //XOffset and YOffset are the distances moved 136 | //XDirection and/or YDirection are/is -1 for mirrored, 1 for not mirrored 137 | { 138 | int x; 139 | int y; 140 | int tempMiddle; 141 | int newCX; 142 | int newCY = YOffset; 143 | int newMX; 144 | int newMY; 145 | if (YDirection < 0) 146 | newCY += mapCornerMaxG; 147 | 148 | for (y = 0; y <= mapCornerMaxG; ++y) 149 | { 150 | if (newCY < 0) 151 | newCY += totalMapSizeG; 152 | else if (newCY >= totalMapSizeG) 153 | newCY -= totalMapSizeG; 154 | 155 | newCX = XOffset; 156 | if (XDirection < 0) 157 | newCX += mapCornerMaxG; 158 | 159 | for (x = 0; x <= mapCornerMaxG; ++x) 160 | { 161 | if (newCX < 0) 162 | newCX += totalMapSizeG; 163 | else if (newCX >= totalMapSizeG) 164 | newCX -= totalMapSizeG; 165 | 166 | mapCorner[newCX][newCY] = mapCorner[x][y]; 167 | if ((x != mapCornerMaxG)&&(y != mapCornerMaxG)) 168 | { 169 | tempMiddle = mapMiddle[x][y]; 170 | newMX = newCX; 171 | newMY = newCY; 172 | if (YDirection < 0) 173 | { 174 | newMY--; 175 | if (newMY == -1) 176 | newMY = totalMapSizeG - 1; 177 | if (tempMiddle == LARGEPOOLTOP) 178 | tempMiddle = LARGEPOOLBOTTOM; 179 | else if (tempMiddle == LARGEPOOLBOTTOM) 180 | tempMiddle = LARGEPOOLTOP; 181 | } 182 | if (XDirection < 0) 183 | { 184 | newMX--; 185 | if (newMX == -1) 186 | newMX = totalMapSizeG - 1; 187 | } 188 | mapMiddle[newMX][newMY] = tempMiddle; 189 | } 190 | 191 | newCX += XDirection; 192 | } 193 | 194 | newCY += YDirection; 195 | } 196 | } 197 | 198 | void mirrorMap() 199 | { 200 | //-------------------------------------------------------------- 201 | // mirror map 202 | //-------------------------------------------------------------- 203 | // normalMirroring() 204 | 205 | int swapXa = pickFrom2(-1,1, 1,advancedMirrorOK_G); 206 | int swapYa = pickFrom2(-1,advancedMirrorOK_G, 1,1); 207 | int swapXb = pickFrom2(-1,advancedMirrorOK_G, 1,1); 208 | int swapYb = pickFrom2(-1,1, 1,advancedMirrorOK_G); 209 | 210 | switch (mirrorTypeG) 211 | { 212 | case NORMALMIRROR: //four quadrants 213 | //ABCBA 214 | //DEFED 215 | //GHIHG 216 | //DEFED 217 | //ABCBA 218 | copyMap(mapCornerMaxG, 0, swapXa, swapYa); 219 | copyMap(0, mapCornerMaxG, swapXb, swapYb); 220 | copyMap(mapCornerMaxG, mapCornerMaxG, swapXa*swapXb, swapYa*swapYb); 221 | break; 222 | case XOFFSETMIRROR: //Like normal, but one half is moved horizontally by 1/4 totalmapsize 223 | //ABABABABA 224 | //DEFGHGFED 225 | //CDCDCDCDC 226 | //FGHGFEDEF 227 | //ABABABABA 228 | if (swapYa == -1) //ensures fairness 229 | swapXb = -1; 230 | copyMap(mapCornerMaxG, 0, 1, swapYa); 231 | copyMap(mapCornerMaxG/2, mapCornerMaxG, swapXb, swapYb); 232 | copyMap(mapCornerMaxG*3/2, mapCornerMaxG, swapXb, swapYa*swapYb); 233 | break; 234 | case YOFFSETMIRROR: //Like normal, but one half is moved vertically by 1/4 totalmapsize 235 | if (swapXb == -1) //ensures fairness 236 | swapYa = -1; 237 | copyMap(mapCornerMaxG, mapCornerMaxG/2, swapXa, swapYa); 238 | copyMap(0, mapCornerMaxG, swapXb, 1); 239 | copyMap(mapCornerMaxG, mapCornerMaxG*3/2, swapXa*swapXb, swapYa); 240 | break; 241 | case MAXDISTMIRROR: //Allows maximum distance between starting points 242 | default: 243 | //ABCDCBA 244 | //E*GHIJE 245 | //HIJE*GH 246 | //DCBABCD 247 | //HG*EJIH 248 | //EJIHG*E 249 | //ABCDCBA 250 | 251 | copyMap(mapCornerMaxG, 0, 1, -1); 252 | copyMap(0, mapCornerMaxG, -1, 1); 253 | copyMap(mapCornerMaxG, mapCornerMaxG, -1, -1); 254 | } 255 | } 256 | 257 | void errorCorrection() 258 | //corrects errors caused by pool placement and mirroring 259 | //doesn't correct mapCorner[x][totalMapSizeG+1] or mapCorner[totalMapSizeG+1][y], since it isn't used 260 | 261 | //for any HIGH to LOW transitions, makes the HIGH MEDIUM 262 | //for pools on nonflat terrain, makes the terrain MEDIUM 263 | //removes invalid water 264 | 265 | { 266 | int x; 267 | int y; 268 | int tempX; 269 | int tempY; 270 | int dx; 271 | int dy; 272 | int redo; 273 | int elev; 274 | 275 | for (y = 0; y < totalMapSizeG; ++y) 276 | for (x = 0; x < totalMapSizeG; ++x) 277 | if (mapCorner[x][y] == HIGH) 278 | for (dy = -1; dy <= 1; ++dy) 279 | { 280 | tempY = y + dy; 281 | if (tempY == totalMapSizeG) 282 | tempY = 0; 283 | else if (tempY == -1) 284 | tempY = totalMapSizeG-1; 285 | 286 | for (dx = -1; dx <= 1; ++dx) 287 | { 288 | tempX = x + dx; 289 | if (tempX == totalMapSizeG) 290 | tempX = 0; 291 | else if (tempX == -1) 292 | tempX = totalMapSizeG-1; 293 | if (mapCorner[tempX][tempY] == LOW) 294 | mapCorner[x][y] = MEDIUM; 295 | } 296 | } 297 | else if ((mapCorner[x][y] != LOW)&&(mapCorner[x][y] != MEDIUM)) 298 | mapCorner[x][y] = MEDIUM; //should not happen anymore 299 | 300 | do 301 | { 302 | redo = 0; 303 | for (y = 0; y < totalMapSizeG; ++y) 304 | for (x = 0; x < totalMapSizeG; ++x) 305 | if (mapMiddle[x][y] != UNASSIGNED) 306 | { 307 | tempY = y + 1; 308 | if (tempY == totalMapSizeG) 309 | tempY = 0; 310 | 311 | tempX = x + 1; 312 | if (tempX == totalMapSizeG) 313 | tempX = 0; 314 | 315 | elev = mapCorner[x][y]; 316 | if ((mapMiddle[x][y] == WATER)&&(elev != LOW)) 317 | mapMiddle[x][y] = UNASSIGNED; 318 | else if ((elev != mapCorner[x][tempY])||(elev != mapCorner[tempX][y])||(elev != mapCorner[tempX][tempY])) 319 | if (mapMiddle[x][y] == WATER) 320 | mapMiddle[x][y] = UNASSIGNED; 321 | else 322 | { 323 | mapCorner[x][y] = MEDIUM; 324 | mapCorner[x][tempY] = MEDIUM; 325 | mapCorner[tempX][y] = MEDIUM; 326 | mapCorner[tempX][tempY] = MEDIUM; 327 | redo = 1; 328 | } 329 | } 330 | } 331 | while (redo); //changing a pool may require others to change (this is the easiest way, not the most efficient) 332 | } 333 | 334 | void generate() 335 | { 336 | //-------------------------------------------------------------- 337 | //initialize 338 | //-------------------------------------------------------------- 339 | int x; 340 | int y; 341 | int neighbors[MAXELEVVAL]; 342 | int a; 343 | int b; 344 | int tempElevation; 345 | int nextElevation; 346 | int special; 347 | 348 | mapCornerMaxG = totalMapSizeG/2; 349 | mapMiddleMaxG = mapCornerMaxG - 1; 350 | 351 | for (y = 0; y <= mapCornerMaxG; ++y) //initialise map to UNASSIGNED tiles 352 | for (x = 0; x <= mapCornerMaxG; ++x) 353 | { 354 | mapCorner[x][y] = UNASSIGNED; 355 | mapMiddle[x][y] = UNASSIGNED; 356 | } 357 | if (advancedMirrorOK_G) 358 | mirrorTypeG = pickFrom4(NORMALMIRROR,1, XOFFSETMIRROR,2, YOFFSETMIRROR,2, MAXDISTMIRROR, 4); 359 | else 360 | mirrorTypeG = NORMALMIRROR; 361 | getSpecials(); //get start and pools 362 | 363 | //-------------------------------------------------------------- 364 | // loop through each square 365 | //-------------------------------------------------------------- 366 | mapCorner[0][0] = pickFrom3(LOW,1, MEDIUM,(terrainSeedFlagG < 9), HIGH,(terrainSeedFlagG < 8)); //seed 367 | // mapCorner[0][0] = LOW;//HIGH;//MEDIUM;// 368 | for (y = 0; y <= mapCornerMaxG; ++y) //fill in the rest of the random map 369 | for (x = 0; x <= mapCornerMaxG; ++x) 370 | { 371 | special = mapMiddle[x][y]; //water wouldn't have been assigned yet, so must be pool, start, or UNASSIGNED 372 | 373 | //-------------------------------------------------------------- 374 | // check neighbors 375 | //-------------------------------------------------------------- 376 | if ((mapCorner[x][y] != UNASSIGNED)&&(mapCorner[x][y] != LOW_OR_WATER)) 377 | nextElevation = mapCorner[x][y]; //already defined because of a special or (0,0), so no change 378 | else 379 | { 380 | neighbors[HIGH] = 0; 381 | neighbors[MEDIUM] = 0; 382 | neighbors[LOW] = 0; 383 | neighbors[WATER] = 0; 384 | 385 | if (x > 0) 386 | { 387 | a = mapCorner[x-1][y]; 388 | if((y > 1)&&(mapMiddle[x-1][y-2] == WATER)) 389 | ++neighbors[WATER]; 390 | if (y > 0) 391 | neighbors[mapCorner[x-1][y-1]] += 3; 392 | } 393 | else 394 | a = mapCorner[x][y-1]; 395 | // { 396 | // a = mapCorner[mapCornerMaxG][y-1]; 397 | // if((y > 1)&&(mapMiddle[mapCornerMaxG][y-2] == WATER)) 398 | // ++neighbors[WATER]; 399 | // } 400 | neighbors[a] += 3; 401 | if (y > 0) 402 | { 403 | b = mapCorner[x][y-1]; 404 | neighbors[b] += 3; 405 | if (x < mapCornerMaxG) 406 | { 407 | ++neighbors[mapCorner[x+1][y-1]]; //so this value can be ignored when choosing water 408 | if ((special != UNASSIGNED)&&(x < mapCornerMaxG-1)) 409 | ++neighbors[mapCorner[x+2][y-1]]; 410 | // else 411 | // ++neighbors[mapCorner[0][y-1]]; 412 | } 413 | // else 414 | // ++neighbors[mapCorner[0][y-1]]; 415 | if((x > 1)&&(mapMiddle[x-2][y-1] == WATER)) 416 | ++neighbors[WATER]; 417 | } 418 | else 419 | b = mapCorner[x-1][y]; // for probability equations for edges 420 | 421 | //-------------------------------------------------------------- 422 | // pick new elevation 423 | //-------------------------------------------------------------- 424 | //neighbors possible new elevation 425 | //HIGH or HIGH with MEDIUM HIGH or MEDIUM 426 | //MEDIUM only HIGH, MEDIUM or LOW 427 | //LOW or WATER only MEDIUM, LOW or WATER 428 | //MEDIUM with LOW or WATER MEDIUM or LOW, possible WATER if no MEDIUM left, down, or down-left 429 | //HIGH with LOW or WATER MEDIUM 430 | #define HIGH_AMT 105 //default elevation distributions 431 | #define MEDIUM_AMT (100+waterAmountG) 432 | #define LOW_AMT (105+3*waterAmountG) 433 | #define WATER_AMT 15*waterAmountG 434 | 435 | if (neighbors[LOW]) 436 | if (neighbors[HIGH]) //HIGH with LOW or WATER 437 | nextElevation = MEDIUM; 438 | else if (neighbors[MEDIUM] >= 3) //MEDIUM with LOW or WATER 439 | if (a != b) 440 | nextElevation = pickFrom2(LOW,LOW_AMT, MEDIUM,MEDIUM_AMT); 441 | else if (a == LOW) 442 | nextElevation = pickFrom2(LOW,100*LOW_AMT, MEDIUM,MEDIUM_AMT*cliffAmountG); 443 | else 444 | nextElevation = pickFrom2(LOW,LOW_AMT*cliffAmountG, MEDIUM,100*MEDIUM_AMT); 445 | else //LOW or WATER only, possibly MEDIUM down-right 446 | if (neighbors[WATER] == 1) 447 | nextElevation = pickFrom3(WATER,100*WATER_AMT, LOW,100*LOW_AMT, MEDIUM,MEDIUM_AMT*cliffAmountG); 448 | else if (neighbors[WATER] == 0) 449 | nextElevation = pickFrom3(WATER,WATER_AMT*cliffAmountG, LOW,100*LOW_AMT, MEDIUM,MEDIUM_AMT*cliffAmountG); 450 | else 451 | nextElevation = pickFrom3(WATER,10000*WATER_AMT, LOW,LOW_AMT*100*cliffAmountG, MEDIUM,MEDIUM_AMT*cliffAmountG*cliffAmountG); 452 | else 453 | if (neighbors[HIGH]) //HIGH or HIGH with MEDIUM 454 | if (a != b) 455 | nextElevation = pickFrom2(MEDIUM,MEDIUM_AMT,HIGH,HIGH_AMT); 456 | else if (a == HIGH) 457 | nextElevation = pickFrom2(MEDIUM,MEDIUM_AMT*cliffAmountG,HIGH,100*HIGH_AMT); 458 | else 459 | nextElevation = pickFrom2(MEDIUM,100*MEDIUM_AMT,HIGH,HIGH_AMT*cliffAmountG); 460 | else //MEDIUM only 461 | nextElevation = pickFrom3(LOW,LOW_AMT*cliffAmountG,MEDIUM,200*MEDIUM_AMT, HIGH,HIGH_AMT*cliffAmountG); 462 | 463 | //-------------------------------------------------------------- 464 | // set elevation 465 | //-------------------------------------------------------------- 466 | if ((mapCorner[x][y] == LOW_OR_WATER)&&(nextElevation != WATER)) 467 | //bottom and left edges of a special on LOW ground there may only be LOW or WATER 468 | nextElevation = LOW; 469 | 470 | if (nextElevation == WATER) 471 | { 472 | if ((x != 0)&&(y != 0)&&(mapMiddle[x-1][y-1] == UNASSIGNED)) 473 | mapMiddle[x-1][y-1] = WATER; //set WATER 474 | nextElevation = LOW; 475 | } 476 | } 477 | 478 | 479 | mapCorner[x][y] = nextElevation; //set elevation 480 | 481 | if (special != UNASSIGNED) //if special, make flat spot (don't worry about going over map edge, will go into mirrored part) 482 | { 483 | tempElevation = nextElevation; 484 | if(tempElevation == LOW) 485 | tempElevation = LOW_OR_WATER; //allow for water on left and bottom edges 486 | mapCorner[x+1][y+1] = nextElevation; 487 | mapCorner[x+1][y] = tempElevation; 488 | mapCorner[x][y+1] = tempElevation; 489 | } 490 | } 491 | 492 | if (islandsFlagG) //replace borders with water, errorCorrection() finishes it. 493 | { 494 | int edgeWaterA = (int)(islandsFlagG * totalMapSizeG / 16 + 0.5); 495 | int edgeWaterB = mapMiddleMaxG-(int)(islandsFlagG * totalMapSizeG / 16); 496 | for (y = 0; y <= mapCornerMaxG; ++y) 497 | { 498 | for (x = 0; x < edgeWaterA; ++x) 499 | { 500 | mapCorner[x][y] = LOW; 501 | mapMiddle[x][y] = WATER; 502 | } 503 | if(mapCorner[edgeWaterA+1][y] == HIGH) 504 | mapCorner[edgeWaterA][y] = MEDIUM; 505 | 506 | for (x = mapMiddleMaxG; x > edgeWaterB; --x) 507 | { 508 | mapCorner[x+1][y] = LOW; 509 | mapMiddle[x][y] = WATER; 510 | } 511 | if(mapCorner[edgeWaterB][y] == HIGH) 512 | mapCorner[edgeWaterB+1][y] = MEDIUM; 513 | } 514 | 515 | for (x = edgeWaterA; x <= edgeWaterB+1; ++x) 516 | { 517 | for (y = 0; y < edgeWaterA; ++y) 518 | { 519 | mapCorner[x][y] = LOW; 520 | mapMiddle[x][y] = WATER; 521 | } 522 | if(mapCorner[x][edgeWaterA+1] == HIGH) 523 | mapCorner[x][edgeWaterA] = MEDIUM; 524 | 525 | for (y = mapMiddleMaxG; y > edgeWaterB; --y) 526 | { 527 | mapCorner[x][y+1] = LOW; 528 | mapMiddle[x][y] = WATER; 529 | } 530 | if(mapCorner[x][edgeWaterB] == HIGH) 531 | mapCorner[x][edgeWaterB+1] = MEDIUM; 532 | } 533 | if (islandsFlagG == 2) //add tiny islands to help bridge wide channels 534 | { 535 | int j; 536 | for (int i = 0; i < totalMapSizeG / 16; ++i) 537 | { 538 | x = (int)(totalMapSizeG / 16 - .5);//SpiffRand((int)(totalMapSizeG / 16 - .5), (int)(totalMapSizeG / 8 - 3)); 539 | y = SpiffRand(x, totalMapSizeG/2 - 1 - x);//(int)(totalMapSizeG / 16 - .5), totalMapSizeG/2-(int)(totalMapSizeG / 16 - .5)); 540 | if (SpiffRand(0,1)) 541 | x = totalMapSizeG / 2 - 1 - x; 542 | if (SpiffRand(0,1)) 543 | { 544 | mapMiddle[x][y] = UNASSIGNED; 545 | for (j = 0; j < 4; ++j) 546 | mapMiddle[x + SpiffRand(-1,1)][y + SpiffRand(-1,1)] = UNASSIGNED; 547 | } 548 | else 549 | { 550 | mapMiddle[y][x] = UNASSIGNED; 551 | for (j = 0; j < 4; ++j) 552 | mapMiddle[y + SpiffRand(-1,1)][x + SpiffRand(-1,1)] = UNASSIGNED; 553 | } 554 | } 555 | } 556 | } 557 | 558 | mirrorMap(); 559 | // stats(); 560 | errorCorrection(); 561 | } 562 | /* 563 | int totalTransitions = 0; 564 | int totalWaterTransitions = 0; 565 | int totalHigh = 0; 566 | int totalMedium = 0; 567 | int totalLow = 0; 568 | int totalWater = 0; 569 | int totalSPools = 0; 570 | int totalMPools = 0; 571 | int totalLPools = 0; 572 | 573 | void stats() 574 | { 575 | int y; 576 | int x; 577 | int t; 578 | int LevelMap[MAXELEVVAL]; 579 | int SPools = 0; 580 | int MPools = 0; 581 | int LPools = 0; 582 | int Transitions = 0; 583 | int WaterTransitions = 0; 584 | 585 | LevelMap[HIGH] = 0; 586 | LevelMap[MEDIUM] = 0; 587 | LevelMap[LOW] = 0; 588 | LevelMap[WATER] = 0; 589 | 590 | for (y = 0; y < totalMapSizeG; ++y) 591 | for (x = 0; x < totalMapSizeG; ++x) 592 | { 593 | t = mapCorner[x][y]; 594 | ++LevelMap[t]; 595 | if (t != mapCorner[(x+1)%totalMapSizeG][y]) 596 | ++Transitions; 597 | if (t != mapCorner[x][(y+1)%totalMapSizeG]) 598 | ++Transitions; 599 | switch (mapMiddle[x][y]) 600 | { 601 | case SMALLPOOL: 602 | ++SPools; 603 | break; 604 | case MEDIUMPOOL: 605 | ++MPools; 606 | break; 607 | case LARGEPOOLTOP: 608 | ++LPools; 609 | break; 610 | case WATER: 611 | ++LevelMap[WATER]; 612 | if (t != mapMiddle[(x+1)%totalMapSizeG][y]) 613 | ++WaterTransitions; 614 | if (t != mapMiddle[x][(y+1)%totalMapSizeG]) 615 | ++WaterTransitions; 616 | 617 | } 618 | } 619 | LevelMap[LOW] -= LevelMap[WATER]; 620 | 621 | cout << "\nH: "; 622 | cout << LevelMap[HIGH]; 623 | cout << "\tM: "; 624 | cout << LevelMap[MEDIUM]; 625 | cout << "\tL: "; 626 | cout << LevelMap[LOW]; 627 | cout << "\tW: "; 628 | cout << LevelMap[WATER]; 629 | cout << "\tSP: "; 630 | cout << SPools; 631 | cout << "\tMP: "; 632 | cout << MPools; 633 | cout << "\tLP: "; 634 | cout << LPools; 635 | cout << "\tT: "; 636 | cout << Transitions; 637 | cout << "\tWT: "; 638 | cout << WaterTransitions; 639 | 640 | totalWaterTransitions += WaterTransitions; 641 | totalTransitions += Transitions; 642 | totalHigh += LevelMap[HIGH]; 643 | totalMedium += LevelMap[MEDIUM]; 644 | totalLow += LevelMap[LOW]; 645 | totalWater += LevelMap[WATER]; 646 | totalSPools += SPools; 647 | totalMPools += MPools; 648 | totalLPools += LPools; 649 | } 650 | 651 | void makeMYCROFTfile() 652 | { 653 | char charOut[MAXELEVVAL]; 654 | 655 | charOut[HIGH] = '2'; 656 | charOut[MEDIUM] = '1'; 657 | charOut[LOW] = '0'; 658 | 659 | cout << "MBCMIF1\n"; 660 | switch (totalMapSizeG) 661 | { 662 | case 32: 663 | cout << "SMALL\n"; 664 | break; 665 | case 40: 666 | cout << "MEDIUM\n"; 667 | break; 668 | case 48: 669 | cout << "LARGE\n"; 670 | break; 671 | case 56: 672 | cout << "HUGE\n"; 673 | break; 674 | case 64: 675 | cout << "SAI\n"; 676 | break; 677 | case 72: 678 | cout << "OBSCENE\n"; 679 | break; 680 | case 80: 681 | cout << "MAX\n"; 682 | break; 683 | default: 684 | cout << "?????\n"; 685 | } 686 | 687 | int y; 688 | int x; 689 | 690 | for (y = 0; y < totalMapSizeG; ++y) 691 | { 692 | for (x = 0; x < totalMapSizeG; ++x) 693 | { 694 | cout << charOut[mapCorner[x][y]]; 695 | cout << ' '; 696 | } 697 | cout << "\n"; 698 | for (x = 0; x < totalMapSizeG; ++x) 699 | switch (mapMiddle[x][y]) 700 | { 701 | case HUB: 702 | cout << "01"; 703 | break; 704 | case SMALLPOOL: 705 | cout << " S"; 706 | break; 707 | case MEDIUMPOOL: 708 | cout << " M"; 709 | break; 710 | case LARGEPOOLTOP: 711 | cout << " L"; 712 | break; 713 | case WATER: 714 | cout << " W"; 715 | break; 716 | case UNASSIGNED: 717 | case LARGEPOOLBOTTOM: 718 | cout << " ."; 719 | break; 720 | default: 721 | cout << "??"; 722 | } 723 | cout << "\n"; 724 | } 725 | } 726 | */ 727 | static void PopulateMIF(MBCMIF &mif) 728 | { 729 | int LevelMap[MAXELEVVAL]; 730 | 731 | LevelMap[HIGH] = 2; 732 | LevelMap[MEDIUM] = 1; 733 | LevelMap[LOW] = 0; 734 | 735 | mif.nVersion = 3; 736 | mif.nDimension = totalMapSizeG; 737 | 738 | int y; 739 | int x; 740 | char t; 741 | int XOffset = SpiffRand(0, totalMapSizeG-1); 742 | int YOffset = SpiffRand(0, totalMapSizeG-1); 743 | int newX; 744 | int newY; 745 | 746 | for (y = 0, newY = YOffset; y < totalMapSizeG; ++y, ++newY) 747 | for (x = 0, newX = XOffset; x < totalMapSizeG; ++x, ++newX) 748 | { 749 | if (newX == totalMapSizeG) 750 | newX = 0; 751 | if (newY == totalMapSizeG) 752 | newY = 0; 753 | mif.aaCornerMap[newX][newY] = LevelMap[mapCorner[x][y]]; 754 | switch (mapMiddle[x][y]) 755 | { 756 | case HUB: 757 | t = -1; 758 | break; 759 | case SMALLPOOL: 760 | t = 'S'; 761 | break; 762 | case MEDIUMPOOL: 763 | t = 'M'; 764 | break; 765 | case LARGEPOOLBOTTOM: 766 | t = 'L'; 767 | break; 768 | case WATER: 769 | t = 'W'; 770 | break; 771 | case UNASSIGNED: 772 | case LARGEPOOLTOP: 773 | t = '.'; 774 | break; 775 | default: 776 | t = '?'; 777 | } 778 | mif.aaCenterMap[newX][newY] = t; 779 | } 780 | } 781 | 782 | void SpiffGenerate (CGameInfo& gi, MBCMIF& mif) 783 | { 784 | int n; 785 | int waterInput = gi.nWater; 786 | 787 | totalMapSizeG = gi.nMapSize; 788 | energyAmountG = (2 + gi.nEnergy) * totalMapSizeG * totalMapSizeG; 789 | 790 | islandsFlagG = pickFrom2(0,1, gi.nWater-4,(gi.nWater >= 5)); //1 is large islands, 2 is small 791 | if (islandsFlagG) 792 | { 793 | waterInput -= 3; 794 | energyAmountG = (int)(energyAmountG * (5-islandsFlagG) / 6); // *2/3 or *1/2 795 | } 796 | 797 | waterAmountG = 4 * waterInput; 798 | cliffAmountG = 1 << gi.nTerrain;//(int)((1 + gi.nTerrain) * (1 + gi.nTerrain) * 3/2); 799 | advancedMirrorOK_G = ((gi.nTerrain > 1) && (waterInput < 6)) || islandsFlagG; 800 | terrainSeedFlagG = 2*waterInput - gi.nTerrain; 801 | 802 | n = (int)(energyAmountG/2700); 803 | if (n > 12) 804 | n = 12; 805 | if (n < 1) 806 | n = 1; 807 | numPoolsG = SpiffRand((int)(energyAmountG/4000)+1, n); 808 | if (numPoolsG > 12) 809 | numPoolsG = 12; 810 | 811 | mif.nTileset = gi.nTileset; 812 | sprintf(mif.szName, "Spiff %04X", gi.nSeed); 813 | 814 | generate(); 815 | 816 | // stats(); 817 | PopulateMIF(mif); 818 | // makeMYCROFTfile(); 819 | } 820 | /* 821 | void SpiffGenerate100 (CGameInfo& gi, MBCMIF& mif) 822 | { 823 | for (int x = 0; x < 100; ++x) 824 | SpiffGenerate(gi, mif); 825 | 826 | cout << "\ntotal H: "; 827 | cout << totalHigh; 828 | cout << "\tM: "; 829 | cout << totalMedium; 830 | cout << "\tL: "; 831 | cout << totalLow; 832 | cout << "\tW: "; 833 | cout << totalWater; 834 | cout << "\tSP: "; 835 | cout << totalSPools; 836 | cout << "\tMP: "; 837 | cout << totalMPools; 838 | cout << "\tLP: "; 839 | cout << totalLPools; 840 | cout << "\tT: "; 841 | cout << totalTransitions; 842 | cout << "\tWT: "; 843 | cout << totalWaterTransitions; 844 | 845 | PopulateMIF(mif); 846 | } 847 | */ 848 | 849 | -------------------------------------------------------------------------------- /MoonbaseConsole/KattonGen.cpp: -------------------------------------------------------------------------------- 1 | /*MBC Random Map Generator by Katton*/ 2 | 3 | #define VERSIONNUM 3.0 4 | #define TEMP_REPLACEMENT_NUMA 5 5 | #define TEMP_REPLACEMENT_NUMB 6 6 | #define TEMP_REPLACEMENT_NUMC 7 7 | #define NEVER_USED_NUM 99 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include "mbcmif.h" 15 | #include "GameInfo.h" 16 | 17 | int size; // 32, 40, 48, or 56 18 | int tileset; 19 | int startloc [20][2]; 20 | int board [MAX_TILE_COUNT][MAX_TILE_COUNT]; 21 | int special [MAX_TILE_COUNT][MAX_TILE_COUNT]; 22 | char mapname[17]; 23 | 24 | 25 | int min (int a, int b, int c); 26 | int distance (int x1, int y1, int x2, int y2); 27 | int plusminus (int max); 28 | int fillboards (int num); 29 | int randomplace (int numberofplaces, int placer); 30 | int randomflip (int numberofplaces, int inWater); 31 | int randomsplotch(int length, int stringiness, int placer, int x, int y); //stringiness: 0 = no change/random, 1 = no back, 2 = back goes forwards 32 | int goodforwater (int x, int y); 33 | int randomwater(int length, int stringiness, int x, int y); 34 | int goodforenergy (int x, int y, int poolsize); 35 | int makeenergy (void); 36 | int findcoord (int value, int move); 37 | int replacenum (int replacee, int replacer); 38 | int fattenone (int x, int y, int howfat, int middle, int ignorer, int replacer); 39 | int fattenall (int howfat, int middle, int ignorer, int replacer); // howfat: postive 1-5 for distance, -100 to 0 for random 3 spread from 2 to 5. 40 | int findstartloc (void); 41 | int whatheightstartloc (int x, int y); 42 | int tileaverage (int x, int y, int threshold); 43 | int saveboard (void); 44 | void KattonGenerate (void); 45 | 46 | static void PopulateMIF (MBCMIF& mif) 47 | { 48 | int i, j; 49 | mif.nVersion = 3; 50 | mif.nDimension = size; 51 | mif.nTileset = tileset; 52 | strcpy (mif.szName, mapname); 53 | for (j=0; j= 1) { 180 | multiplier = (int) ( (float) numwaterplaces/ (float) numwatersplotches); 181 | 182 | for (i=0; i= 90) { 192 | maxnumclose = 2; 193 | maxnumfar = 3; 194 | maxnumrand = (int) (size*size/150); 195 | smallmed = 2; 196 | } 197 | else if (inEnergy >= 75) { 198 | maxnumclose = 2; 199 | maxnumfar = 1; 200 | maxnumrand = (int) (size*size/250)+4; 201 | smallmed = 3; 202 | } 203 | else if (inEnergy >= 60) { 204 | maxnumclose = 1; 205 | maxnumfar = 2; 206 | maxnumrand = (int) (size*size/250); 207 | smallmed = 4; 208 | } 209 | else if (inEnergy >= 45) { 210 | maxnumclose = 1; 211 | maxnumfar = 1; 212 | maxnumrand = (int) (size*size/250); 213 | smallmed = 6; 214 | } 215 | else if (inEnergy >= 30) { 216 | maxnumclose = 1; 217 | maxnumfar = 0; 218 | maxnumrand = (int) (size*size/350)+2; 219 | smallmed = 8; 220 | } 221 | else if (inEnergy >= 15) { 222 | maxnumclose = 0; 223 | maxnumfar = 1; 224 | maxnumrand = (int) (size*size/450); 225 | smallmed = 10; 226 | } 227 | else if (inEnergy >= 0) { 228 | maxnumclose = 0; 229 | maxnumfar = 0; 230 | maxnumrand = 0; 231 | smallmed = 1; 232 | } 233 | 234 | 235 | for (i=0; i<4; i++) { 236 | numplaceClose = 0; 237 | numplaceFar = 0; 238 | for (j=0; j= (int) (size/10)) && (distance(startloc[i][0], startloc[i][1], j, k) <= (int) (size/8))) { 241 | goodplaceClose[numplaceClose][0] = j; 242 | goodplaceClose[numplaceClose][1] = k; 243 | numplaceClose++; 244 | } 245 | else if ((goodforenergy(j, k, 0)) && (distance(startloc[i][0], startloc[i][1], j, k) >= (int) (size/7)) && (distance(startloc[i][0], startloc[i][1], j, k) <= (int) (size/5))) { 246 | goodplaceFar[numplaceFar][0] = j; 247 | goodplaceFar[numplaceFar][1] = k; 248 | numplaceFar++; 249 | } 250 | } 251 | } 252 | if (numplaceClose >= 1) { 253 | placeClose[0] = rand()%(int)(numplaceClose/2) + 1; 254 | } 255 | if (numplaceClose >= 2) { 256 | placeClose[1] = rand()%(int)(numplaceClose/2) + (int)(numplaceClose/2) - 1; 257 | } 258 | 259 | if (numplaceClose >= maxnumclose) { 260 | for (l = 0; l < maxnumclose; l++) { 261 | special[ goodplaceClose[placeClose[l]][0] ] [ goodplaceClose[placeClose[l]][1] ] = 100; 262 | } 263 | } 264 | else { 265 | for (l = 0; l < numplaceClose; l++) { 266 | special[ goodplaceClose[placeClose[l]][0] ] [ goodplaceClose[placeClose[l]][1] ] = 100; 267 | } 268 | } 269 | 270 | if (numplaceFar >= 1) { 271 | placeFar[0] = rand()%(int)(numplaceFar/3) + 1; 272 | } 273 | if (numplaceFar >= 2) { 274 | placeFar[1] = rand()%(int)(numplaceFar/3) + (int)(numplaceClose/3); 275 | } 276 | if (numplaceFar >= 3) { 277 | placeFar[2] = rand()%(int)(numplaceFar/3) + (int)(2 * numplaceClose/3) - 1; 278 | } 279 | 280 | if (numplaceFar >= maxnumfar) { 281 | for (l = 0; l < maxnumfar; l++) { 282 | special[goodplaceFar[placeFar[l]][0]][goodplaceFar[placeFar[l]][1]] = 100; 283 | } 284 | } 285 | else { 286 | for (l = 0; l < numplaceFar; l++) { 287 | special[goodplaceFar[placeFar[l]][0]][goodplaceFar[placeFar[l]][1]] = 100; 288 | } 289 | } 290 | } 291 | 292 | 293 | 294 | counter = 0; 295 | counterpools = 4 * (maxnumfar + maxnumclose); 296 | for (k=0; k=10) && (distance ( i, j, startloc[1][0], startloc[1][1] ) >=10) && (distance ( i, j, startloc[2][0], startloc[2][1] ) >=10) && (distance ( i, j, startloc[3][0], startloc[3][1] ) >=10) && (goodforenergy(i, j, 1) ) && (counter < 5000))); 303 | if (rand()%smallmed == 0 ) { 304 | special[i][j] = 200; 305 | counterpools++; 306 | } 307 | else { 308 | special[i][j] = 100; 309 | counterpools++; 310 | } 311 | } 312 | 313 | 314 | //****************************************Do that saving thing that you do, BABY! 315 | PopulateMIF(mif); 316 | } 317 | 318 | int distance (int x1, int y1, int x2, int y2) { 319 | int dx, dy, disp; 320 | dx = min ((abs (x1 - x2)), (abs (x1+size - x2)), (abs (x2+size - x1))); 321 | dy = min ((abs (y1 - y2)), (abs (y1+size - y2)), (abs (y2+size - y1))); 322 | disp = (int) sqrt((double) (dx * dx + dy * dy )); 323 | return disp; 324 | } 325 | 326 | int min (int a, int b, int c) { 327 | if ( (a <= b) && (a <= c) ) { 328 | return a; 329 | } 330 | if ( (b < a) && (b <= c) ) { 331 | return b; 332 | } 333 | if ( (c < a) && (c < b) ) { 334 | return c; 335 | } 336 | else { 337 | return a; 338 | } 339 | } 340 | 341 | int goodforenergy (int x, int y, int poolsize) { 342 | switch (poolsize) { 343 | case 0: 344 | if ((board[x][y] == board[findcoord(x,+1)][y]) && (board[findcoord(x,+1)][y] == board[x][findcoord(y,+1)]) && (board[x][findcoord(y,+1)] == board[findcoord(x,+1)][findcoord(y,+1)])) { 345 | //check main map 346 | if (special[x][y] == 0) { //specials are clear 347 | return 1; 348 | } 349 | else { 350 | return 0; 351 | } 352 | } 353 | else { 354 | return 0; 355 | } 356 | case 1: 357 | if ((board[x][y] == board[findcoord(x,+1)][y]) && (board[findcoord(x,+1)][y] == board[x][findcoord(y,+1)]) && (board[x][findcoord(y,+1)] == board[findcoord(x,+1)][findcoord(y,+1)])) { //check main map 358 | if ((special[x][y] == 0) && (special[findcoord(x,+1)][y] == 0) && (special[x][findcoord(y,+1)] == 0) && (special[findcoord(x,+1)][findcoord(y,+1)] == 0)){ //specials are clear 359 | return 1; 360 | } 361 | else { 362 | return 0; 363 | } 364 | } 365 | else { 366 | return 0; 367 | } 368 | default: 369 | return 0; 370 | } 371 | } 372 | 373 | int plusminus (int max) { 374 | int result = rand()%(max +1); 375 | if (rand()%2 == 0) { 376 | result *= (-1); 377 | } 378 | return result; 379 | } 380 | 381 | int fillboards (int num) { 382 | int i, j; 383 | for (i=0; i < size; i++) { 384 | for (j=0; j < size; j++) { 385 | board[i][j] = num; 386 | special[i][j] = num; 387 | } 388 | } 389 | return 0; 390 | } 391 | 392 | int randomplace (int numberofplaces, int placer) { 393 | int i, randx, randy; 394 | for (i=0; i< numberofplaces; i++) { 395 | randx = (rand()%size); 396 | randy = (rand()%size); 397 | board[randx][randy] = placer; 398 | } 399 | return 0; 400 | } 401 | 402 | int randomsplotch(int length, int stringiness, int placer, int x, int y) { 403 | int currx, curry, direction = 10, prevdirection, movex, movey, i=0; 404 | currx = x; 405 | curry = y; 406 | while (i<= length) { 407 | board[currx][curry] = placer; 408 | prevdirection = direction; 409 | direction = (rand()%4); 410 | if ((((direction + 2)==prevdirection)||((direction - 2) == prevdirection))&&(stringiness==2)) { 411 | direction = prevdirection; 412 | } 413 | if (!((((direction + 2)==prevdirection)||((direction - 2) == prevdirection))&&(stringiness==1))) { 414 | switch (direction) { 415 | case 0: 416 | movex=0; 417 | movey=1; 418 | break; 419 | case 1: 420 | movex=1; 421 | movey=0; 422 | break; 423 | case 2: 424 | movex=0; 425 | movey=-1; 426 | break; 427 | case 3: 428 | movex=-1; 429 | movey=0; 430 | break; 431 | } 432 | currx = findcoord(currx, movex); 433 | curry = findcoord(curry, movey); 434 | i++; 435 | } 436 | } 437 | return 0; 438 | } 439 | 440 | int findcoord (int value, int move) { 441 | move = move%size; 442 | int final = value+move; 443 | if (final < 0) { 444 | final = size + final; 445 | } 446 | if (final >= size) { 447 | final = final%size ; 448 | } 449 | return final; 450 | } 451 | 452 | int replacenum (int replacee, int replacer) { 453 | int i, j; 454 | for (j=0; j= 6) { 475 | temp = 5; 476 | } 477 | fattenone (i, j, temp, middle, ignorer, replacer); 478 | } 479 | else { 480 | fattenone (i, j, howfat, middle, ignorer, replacer); 481 | } 482 | } 483 | } 484 | } 485 | return 0; 486 | } 487 | int fattenone (int x, int y, int howfat, int middle, int ignorer, int 488 | replacer) { 489 | if (howfat==-100) { 490 | board[x][y] = replacer; 491 | board[findcoord(x,+1)][y] = replacer; 492 | board[x][findcoord(y,+1)] = replacer; 493 | board[findcoord(x,+1)][findcoord(y,+1)] = replacer; 494 | } 495 | if (howfat>=1) { 496 | board[x][findcoord(y,-1)] = ((board[x][findcoord(y,-1)]==middle)||(board[x][findcoord(y,-1)]==ignorer))?board[x][findcoord(y,-1)]:replacer; 497 | board[x][findcoord(y,+1)] = ((board[x][findcoord(y,+1)]==middle)||(board[x][findcoord(y,+1)]==ignorer))?board[x][findcoord(y,+1)]:replacer; 498 | board[findcoord(x,-1)][y] = ((board[findcoord(x,-1)][y]==middle)||(board[findcoord(x,-1)][y]==ignorer))?board[findcoord(x,-1)][y]:replacer; 499 | board[findcoord(x,+1)][y] = ((board[findcoord(x,+1)][y]==middle)||(board[findcoord(x,+1)][y]==ignorer))?board[findcoord(x,+1)][y]:replacer; 500 | } 501 | if (howfat>=2) { 502 | board[findcoord(x,-1)][findcoord(y,-1)] = ((board[findcoord(x,-1)][findcoord(y,-1)]==middle)||(board[findcoord(x,-1)][findcoord(y,-1)]==ignorer))?board[findcoord(x,-1)][findcoord(y,-1)]:replacer; 503 | board[findcoord(x,-1)][findcoord(y,+1)] = ((board[findcoord(x,-1)][findcoord(y,+1)]==middle)||(board[findcoord(x,-1)][findcoord(y,+1)]==ignorer))?board[findcoord(x,-1)][findcoord(y,+1)]:replacer; 504 | board[findcoord(x,+1)][findcoord(y,-1)] = ((board[findcoord(x,+1)][findcoord(y,-1)]==middle)||(board[findcoord(x,+1)][findcoord(y,-1)]==ignorer))?board[findcoord(x,+1)][findcoord(y,-1)]:replacer; 505 | board[findcoord(x,+1)][findcoord(y,+1)] = ((board[findcoord(x,+1)][findcoord(y,+1)]==middle)||(board[findcoord(x,+1)][findcoord(y,+1)]==ignorer))?board[findcoord(x,+1)][findcoord(y,+1)]:replacer; 506 | } 507 | if (howfat>=3) { 508 | board[x][findcoord(y,-2)] = ((board[x][findcoord(y,-2)]==middle)||(board[x][findcoord(y,-2)]==ignorer))?board[x][findcoord(y,-2)]:replacer; 509 | board[x][findcoord(y,+2)] = ((board[x][findcoord(y,+2)]==middle)||(board[x][findcoord(y,+2)]==ignorer))?board[x][findcoord(y,+2)]:replacer; 510 | board[findcoord(x,-2)][y] = ((board[findcoord(x,-2)][y]==middle)||(board[findcoord(x,-2)][y]==ignorer))?board[findcoord(x,-2)][y]:replacer; 511 | board[findcoord(x,+2)][y] = ((board[findcoord(x,+2)][y]==middle)||(board[findcoord(x,+2)][y]==ignorer))?board[findcoord(x,+2)][y]:replacer; 512 | } 513 | if (howfat>=4) { 514 | board[findcoord(x,-1)][findcoord(y,-2)] = ((board[findcoord(x,-1)][findcoord(y,-2)]==middle)||(board[findcoord(x,-1)][findcoord(y,-2)]==ignorer))?board[findcoord(x,-1)][findcoord(y,-2)]:replacer; 515 | board[findcoord(x,-1)][findcoord(y,+2)] = ((board[findcoord(x,-1)][findcoord(y,+2)]==middle)||(board[findcoord(x,-1)][findcoord(y,+2)]==ignorer))?board[findcoord(x,-1)][findcoord(y,+2)]:replacer; 516 | board[findcoord(x,+1)][findcoord(y,-2)] = ((board[findcoord(x,+1)][findcoord(y,-2)]==middle)||(board[findcoord(x,+1)][findcoord(y,-2)]==ignorer))?board[findcoord(x,+1)][findcoord(y,-2)]:replacer; 517 | board[findcoord(x,+1)][findcoord(y,+2)] = ((board[findcoord(x,+1)][findcoord(y,+2)]==middle)||(board[findcoord(x,+1)][findcoord(y,+2)]==ignorer))?board[findcoord(x,+1)][findcoord(y,+2)]:replacer; 518 | 519 | board[findcoord(x,-2)][findcoord(y,-1)] = ((board[findcoord(x,-2)][findcoord(y,-1)]==middle)||(board[findcoord(x,-2)][findcoord(y,-1)]==ignorer))?board[findcoord(x,-2)][findcoord(y,-1)]:replacer; 520 | board[findcoord(x,-2)][findcoord(y,+1)] = ((board[findcoord(x,-2)][findcoord(y,+1)]==middle)||(board[findcoord(x,-2)][findcoord(y,+1)]==ignorer))?board[findcoord(x,-2)][findcoord(y,+1)]:replacer; 521 | board[findcoord(x,+2)][findcoord(y,-1)] = ((board[findcoord(x,+2)][findcoord(y,-1)]==middle)||(board[findcoord(x,+2)][findcoord(y,-1)]==ignorer))?board[findcoord(x,+2)][findcoord(y,-1)]:replacer; 522 | board[findcoord(x,+2)][findcoord(y,+1)] = ((board[findcoord(x,+2)][findcoord(y,+1)]==middle)||(board[findcoord(x,+2)][findcoord(y,+1)]==ignorer))?board[findcoord(x,+2)][findcoord(y,+1)]:replacer; 523 | } 524 | if (howfat>=5) { 525 | board[findcoord(x,-2)][findcoord(y,-2)] = ((board[findcoord(x,-2)][findcoord(y,-2)]==middle)||(board[findcoord(x,-2)][findcoord(y,-2)]==ignorer))?board[findcoord(x,-2)][findcoord(y,-2)]:replacer; 526 | board[findcoord(x,-2)][findcoord(y,+2)] = ((board[findcoord(x,-2)][findcoord(y,+2)]==middle)||(board[findcoord(x,-2)][findcoord(y,+2)]==ignorer))?board[findcoord(x,-2)][findcoord(y,+2)]:replacer; 527 | board[findcoord(x,+2)][findcoord(y,-2)] = ((board[findcoord(x,+2)][findcoord(y,-2)]==middle)||(board[findcoord(x,+2)][findcoord(y,-2)]==ignorer))?board[findcoord(x,+2)][findcoord(y,-2)]:replacer; 528 | board[findcoord(x,+2)][findcoord(y,+2)] = ((board[findcoord(x,+2)][findcoord(y,+2)]==middle)||(board[findcoord(x,+2)][findcoord(y,+2)]==ignorer))?board[findcoord(x,+2)][findcoord(y,+2)]:replacer; 529 | 530 | board[x][findcoord(y,-3)] = ((board[x][findcoord(y,-3)]==middle)||(board[x][findcoord(y,-3)]==ignorer))?board[x][findcoord(y,-3)]:replacer; 531 | board[x][findcoord(y,+3)] = ((board[x][findcoord(y,+3)]==middle)||(board[x][findcoord(y,+3)]==ignorer))?board[x][findcoord(y,+3)]:replacer; 532 | board[findcoord(x,-3)][y] = ((board[findcoord(x,-3)][y]==middle)||(board[findcoord(x,-3)][y]==ignorer))?board[findcoord(x,-3)][y]:replacer; 533 | board[findcoord(x,+3)][y] = ((board[findcoord(x,+3)][y]==middle)||(board[findcoord(x,+3)][y]==ignorer))?board[findcoord(x,+3)][y]:replacer; 534 | } 535 | return 0; 536 | } 537 | 538 | int findstartloc (void) { 539 | int temp, i, j, shiftx, shifty, secondshift; 540 | int start[4][2]; 541 | shiftx = rand()%size; 542 | shifty = rand()%size; 543 | start[0][0] = findcoord((int) size/4, (plusminus(3) + shiftx)); 544 | start[0][1] = findcoord((int) size/4, (plusminus(3) + shifty)); 545 | start[1][0] = findcoord((int) 3 * size/4, (plusminus(3) + shiftx)); 546 | start[1][1] = findcoord((int) size/4, (plusminus(3) + shifty)); 547 | start[2][0] = findcoord((int) size/4, (plusminus(3) + shiftx)); 548 | start[2][1] = findcoord((int) 3 * size/4, (plusminus(3) + shifty)); 549 | start[3][0] = findcoord((int) 3 * size/4, (plusminus(3) + shiftx)); 550 | start[3][1] = findcoord((int) 3 * size/4, (plusminus(3) + shifty)); 551 | 552 | temp = rand()%2; 553 | secondshift = rand()%size; 554 | 555 | if (temp == 0) { 556 | start[0][0] = findcoord(start[0][0], secondshift); 557 | start[1][0] = findcoord(start[1][0], secondshift); 558 | } 559 | 560 | else { 561 | start[1][1] = findcoord(start[1][1], secondshift); 562 | start[3][1] = findcoord(start[3][1], secondshift); 563 | } 564 | 565 | temp = whatheightstartloc(start[0][0], start[0][1]); 566 | fattenone (start[0][0], start[0][1], -100, temp, NEVER_USED_NUM, temp); 567 | 568 | temp = whatheightstartloc(start[1][0], start[1][1]); 569 | fattenone (start[1][0], start[1][1], -100, temp, NEVER_USED_NUM, temp); 570 | 571 | temp = whatheightstartloc(start[2][0], start[2][1]); 572 | fattenone (start[2][0], start[2][1], -100, temp, NEVER_USED_NUM, temp); 573 | 574 | temp = whatheightstartloc(start[3][0], start[3][1]); 575 | fattenone (start[3][0], start[3][1], -100, temp, NEVER_USED_NUM, temp); 576 | 577 | for (j=0; j < 4; j++) { 578 | for (i=0; i < 2; i++) { 579 | startloc[j][i] = start[j][i]; 580 | } 581 | } 582 | 583 | temp = rand()%4; 584 | j = 4; 585 | for (i=0; i<4; i++) { 586 | if (temp == i) { 587 | } 588 | else { 589 | startloc[j][0] = start[i][0]; 590 | startloc[j][1] = start[i][1]; 591 | j++; 592 | } 593 | } 594 | 595 | startloc[7][0] = startloc[4][0]; 596 | startloc[7][1] = startloc[4][1]; 597 | startloc[8][0] = startloc[6][0]; 598 | startloc[8][1] = startloc[6][1]; 599 | 600 | for (j=9; j < 13; j++) { 601 | for (i=0; i < 2; i++) { 602 | startloc[j][i] = start[j-9][i]; 603 | } 604 | } 605 | 606 | for (j=13; j < 17; j++) { 607 | for (i=0; i < 2; i++) { 608 | startloc[j][i] = start[j-13][i]; 609 | } 610 | } 611 | 612 | for (j=17; j < 20; j++) { 613 | for (i=0; i < 2; i++) { 614 | startloc[j][i] = startloc[j-13][i]; 615 | } 616 | } 617 | 618 | //place on special map 619 | for (i=0; i<4; i++) { 620 | special[startloc[i][0]][startloc[i][1]] += 1; 621 | } 622 | for (i=4; i<7; i++) { 623 | special[startloc[i][0]][startloc[i][1]] += 2; 624 | } 625 | for (i=7; i<9; i++) { 626 | special[startloc[i][0]][startloc[i][1]] += 4; 627 | } 628 | for (i=9; i<13; i++) { 629 | special[startloc[i][0]][startloc[i][1]] += 8; 630 | } 631 | for (i=13; i<17; i++) { 632 | special[startloc[i][0]][startloc[i][1]] += 16; 633 | } 634 | for (i=17; i<20; i++) { 635 | special[startloc[i][0]][startloc[i][1]] += 32; 636 | } 637 | return 0; 638 | } 639 | 640 | int whatheightstartloc (int x, int y) { 641 | int heightfield[3] = {0, 0, 0}; 642 | 643 | heightfield[board[findcoord(x,+2)][findcoord(y,-1)]]++; 644 | heightfield[board[findcoord(x,+2)][y]]++; 645 | heightfield[board[findcoord(x,+2)][findcoord(y,+1)]]++; 646 | heightfield[board[findcoord(x,+2)][findcoord(y,+2)]]++; 647 | 648 | heightfield[board[findcoord(x,-1)][findcoord(y,-1)]]++; 649 | heightfield[board[findcoord(x,-1)][y]]++; 650 | heightfield[board[findcoord(x,-1)][findcoord(y,+1)]]++; 651 | heightfield[board[findcoord(x,-1)][findcoord(y,+2)]]++; 652 | 653 | heightfield[board[x][findcoord(y,-1)]]++; 654 | heightfield[board[x][y]]++; 655 | heightfield[board[x][findcoord(y,+1)]]++; 656 | heightfield[board[x][findcoord(y,+2)]]++; 657 | 658 | heightfield[board[findcoord(x,+1)][findcoord(y,-1)]]++; 659 | heightfield[board[findcoord(x,+1)][y]]++; 660 | heightfield[board[findcoord(x,+1)][findcoord(y,+1)]]++; 661 | heightfield[board[findcoord(x,+1)][findcoord(y,+2)]]++; 662 | 663 | if (heightfield[0] == 0) { 664 | if (heightfield[1] >= heightfield[2]) { 665 | return 1; 666 | } 667 | else { 668 | return 2; 669 | } 670 | } 671 | else if (heightfield[1] == 0) { 672 | if (heightfield[0] >= heightfield[2]) { 673 | return 0; 674 | } 675 | else { 676 | return 2; 677 | } 678 | } 679 | else if (heightfield[2] == 0) { 680 | if (heightfield[1] >= heightfield[0]) { 681 | return 1; 682 | } 683 | else { 684 | return 0; 685 | } 686 | } 687 | else { 688 | return 1; 689 | } 690 | } 691 | 692 | int goodforwater (int x, int y) { 693 | if ((board[x][y] == 0) && (board[findcoord(x,+1)][y] == 0) && (board[x][findcoord(y,+1)] == 0) && (board[findcoord(x,+1)][findcoord(y,+1)] == 0)) { //check main map 694 | if ((special[x][y] <= 0) && (special[x][findcoord(y, 1)] <= 0) && (special[findcoord(x, 1)][findcoord(y, 1)] <= 0) && (special[findcoord(x, 1)][y] <= 0) && (special[findcoord(x, 1)][findcoord(y, -1)] <= 0) && (special[x][findcoord(y, -1)] <= 0) && (special[findcoord(x, -1)][findcoord(y, -1)] <= 0) && (special[findcoord(x, -1)][y] <= 0) && (special[findcoord(x, -1)][findcoord(y, 1)] <= 0)) { //specials are clear 695 | return 1; 696 | } 697 | else { 698 | return 0; 699 | } 700 | } 701 | else { 702 | return 0; 703 | } 704 | } 705 | 706 | int randomwater(int length, int stringiness, int x, int y) { 707 | int currx, curry, direction = 10, prevdirection, i=0; 708 | currx = x; 709 | curry = y; 710 | while (i<= length) { 711 | special[currx][curry] = -1; 712 | prevdirection = direction; 713 | direction = (rand()%4); 714 | if ((((direction + 2)==prevdirection)||((direction - 2) == prevdirection))&&(stringiness==2)) { 715 | direction = prevdirection; 716 | } 717 | if (!((((direction + 2)==prevdirection)||((direction - 2) == prevdirection))&&(stringiness==1))) { 718 | switch (direction) { 719 | 720 | case 0: //north 721 | if (goodforwater(currx, findcoord(curry, 1))) { 722 | curry = findcoord(curry, 1); 723 | } 724 | break; 725 | 726 | case 1: //east 727 | if (goodforwater(findcoord(currx, 1), curry)) { 728 | currx = findcoord(currx, 1); 729 | } 730 | break; 731 | 732 | case 2: //south 733 | if (goodforwater(currx, findcoord(curry, -1))) { 734 | curry = findcoord(curry, -1); 735 | } 736 | break; 737 | 738 | case 3: //west 739 | if (goodforwater(findcoord(currx, -1), curry)) { 740 | currx = findcoord(currx, -1); 741 | } 742 | break; 743 | } 744 | i++; 745 | } 746 | } 747 | return 0; 748 | } 749 | 750 | int tileaverage (int x, int y, int threshold) { 751 | int heightfield[3] = {0, 0, 0}; 752 | 753 | heightfield[board[findcoord(x,-1)][findcoord(y,-1)]]++; 754 | heightfield[board[findcoord(x,-1)][y]]++; 755 | heightfield[board[findcoord(x,-1)][findcoord(y,+1)]]++; 756 | 757 | heightfield[board[x][findcoord(y,-1)]]++; 758 | heightfield[board[x][y]]++; 759 | heightfield[board[x][findcoord(y,+1)]]++; 760 | 761 | heightfield[board[findcoord(x,+1)][findcoord(y,-1)]]++; 762 | heightfield[board[findcoord(x,+1)][y]]++; 763 | heightfield[board[findcoord(x,+1)][findcoord(y,+1)]]++; 764 | 765 | if ((heightfield[2] == 0) && (heightfield[1] < heightfield[0]) && (heightfield[0] >= threshold)) { 766 | board[x][y] = 0; 767 | return 0; 768 | } 769 | else if ((heightfield[0] == 0) && (heightfield[1] < heightfield[2]) && (heightfield[2] >= threshold)) { 770 | board[x][y] = 2; 771 | return 2; 772 | } 773 | else if (heightfield[1] >= threshold) { 774 | board[x][y] = 1; 775 | return 1; 776 | } 777 | else { 778 | return 0; 779 | } 780 | } 781 | 782 | int randomflip (int numberofplaces, int inWater) { 783 | int i, x, y, temp; 784 | for (i = 0; i < numberofplaces; i++) { 785 | x = rand()%size; 786 | y = rand()%size; 787 | if (board[x][y] == 0) { 788 | temp = rand()%inWater; 789 | if (temp <= 50) { 790 | board[x][y] = 1; 791 | } 792 | } 793 | else if (board[x][y] == 2) { 794 | board[x][y] = 1; 795 | } 796 | else if (board[x][y] == 1) { 797 | 798 | temp = rand()%2; 799 | int heightfield[3] = {0, 0, 0}; 800 | 801 | heightfield[board[findcoord(x,-1)][findcoord(y,-1)]]++; 802 | heightfield[board[findcoord(x,-1)][y]]++; 803 | heightfield[board[findcoord(x,-1)][findcoord(y,+1)]]++; 804 | 805 | heightfield[board[x][findcoord(y,-1)]]++; 806 | heightfield[board[x][findcoord(y,+1)]]++; 807 | 808 | heightfield[board[findcoord(x,+1)][findcoord(y,-1)]]++; 809 | heightfield[board[findcoord(x,+1)][y]]++; 810 | heightfield[board[findcoord(x,+1)][findcoord(y,+1)]]++; temp = rand()%2; 811 | if (heightfield[0] == 0) { 812 | board[x][y] = 2; 813 | } 814 | else if (heightfield[2] == 0){ 815 | board[x][y] = 0; 816 | } 817 | } 818 | } 819 | return 0; 820 | } 821 | 822 | int wateraverage (int x, int y, int threshold) { 823 | int total = 0; 824 | 825 | total = (special[findcoord(x,-1)][findcoord(y,-1)] == -1)?total + 1:total; 826 | total = (special[findcoord(x,-1)][y] == -1)?total + 1:total; 827 | total = (special[findcoord(x,-1)][findcoord(y,+1)] == -1)?total + 1:total; 828 | total = (special[x][findcoord(y,-1)] == -1)?total + 1:total; 829 | total = (special[x][findcoord(y,+1)] == -1)?total + 1:total; 830 | total = (special[findcoord(x,+1)][findcoord(y,-1)] == -1)?total + 1:total; 831 | total = (special[findcoord(x,+1)][y] == -1)?total + 1:total; 832 | total = (special[findcoord(x,+1)][findcoord(y,+1)] == -1)?total + 1:total; 833 | 834 | if ((total >= threshold) && (goodforwater (x, y))) { 835 | special[x][y] = -1; 836 | } 837 | return 0; 838 | } 839 | 840 | int saveboard (void) { 841 | int i, j; 842 | FILE * savefile; 843 | savefile = fopen ("mapoutput.txt", "w"); 844 | for (j=0; j < size; j++) { 845 | for (i=0; i < size; i++) { 846 | fprintf (savefile, "%d", board[i][j]); 847 | } 848 | fprintf (savefile, "\n"); 849 | } 850 | fprintf(savefile, "4 Player Starts:\n(%d,%d), (%d,%d), (%d,%d), (%d,%d)\n", startloc [0][0], startloc [0][1], startloc [1][0], startloc [1][1], startloc [2][0], startloc [2][1], startloc [3][0], startloc [3][1]); 851 | fprintf(savefile, "3 Player Starts:\n(%d,%d), (%d,%d), (%d,%d)\n", startloc [4][0], startloc [4][1],startloc [5][0], startloc [5][1],startloc [6][0], startloc [6][1]); 852 | fprintf(savefile, "2 Player Starts:\n(%d,%d), (%d,%d)\n", startloc [7][0], startloc [7][1],startloc [8][0], startloc [8][1]); 853 | fprintf(savefile, "2v2 Player Starts:\n(%d,%d), (%d,%d), (%d,%d), (%d,%d)\n", startloc [9][0], startloc [9][1],startloc [10][0], startloc [10][1],startloc [11][0], startloc [11][1],startloc [12][0], startloc [12][1]); 854 | fprintf(savefile, "1v3 Player Starts:\n(%d,%d), (%d,%d), (%d,%d), (%d,%d)\n", startloc [13][0], startloc [13][1],startloc [14][0], startloc [14][1],startloc [15][0], startloc [15][1],startloc [16][0], startloc [16][1]); 855 | fprintf(savefile, "1v2 Player Starts:\n(%d,%d), (%d,%d), (%d,%d)\n", startloc [17][0], startloc [17][1],startloc [18][0], startloc [18][1],startloc [19][0], startloc [19][1]); 856 | 857 | for (j=0; j < size; j++) { 858 | for (i=0; i < size; i++) { 859 | if (special[j][i] == 100) { 860 | fprintf (savefile, "S"); 861 | } 862 | else if (special[j][i] == 0) { 863 | fprintf (savefile, "."); 864 | } 865 | else { 866 | fprintf (savefile, "#"); 867 | } 868 | } 869 | fprintf (savefile, "\n"); 870 | } 871 | fclose (savefile); 872 | return 0; 873 | } 874 | 875 | -------------------------------------------------------------------------------- /Common/mbcmif.cpp: -------------------------------------------------------------------------------- 1 | #include "mbcmif.h" 2 | #include 3 | 4 | #include // TODO: Remove this 5 | 6 | 7 | 8 | // This array maps the neighbors of a tile to what water tile should be used. 9 | // This is based on a system with the most significant bit in the upper left 10 | // and the least significant in the lower right. A zero bit means a water 11 | // neighbor and a one bit means a land neighbor. Some examples: 12 | // 13 | // WWW 14 | // WWW = index 0x00 in the array, a full water tile 15 | // WWW 16 | // 17 | // .W. 18 | // WWW = index 0xA5 in the array, an interesction tile 19 | // .W. 20 | // 21 | // ... 22 | // .W. = index 0xFF in the array, a puddle tile 23 | // ... 24 | // 25 | // To say that this was tedious to generate doesn't really tell the whole story... 26 | 27 | BYTE aWaterTileMapG[] = { 28 | 0x44, 0x40, 0x32, 0x32, 0x3C, 0x38, 0x32, 0x32, // 0x00 29 | 0x2C, 0x2C, 0x26, 0x26, 0x2A, 0x2A, 0x26, 0x26, 30 | 0x2F, 0x2D, 0x27, 0x27, 0x2F, 0x2D, 0x27, 0x27, // 0x10 31 | 0x1B, 0x1B, 0x49, 0x49, 0x1B, 0x1B, 0x49, 0x49, 32 | 0x42, 0x3E, 0x30, 0x30, 0x3A, 0x36, 0x30, 0x30, // 0x20 33 | 0x2C, 0x2C, 0x26, 0x26, 0x2A, 0x2A, 0x26, 0x26, 34 | 0x2E, 0x22, 0x1E, 0x1E, 0x2E, 0x22, 0x1E, 0x1E, // 0x30 35 | 0x1B, 0x1B, 0x49, 0x49, 0x1B, 0x1B, 0x49, 0x49, 36 | 0x35, 0x33, 0x1C, 0x1C, 0x34, 0x24, 0x1C, 0x1C, // 0x40 37 | 0x28, 0x28, 0x4B, 0x4B, 0x1F, 0x1F, 0x4B, 0x4B, 38 | 0x29, 0x20, 0x4C, 0x4C, 0x29, 0x20, 0x4C, 0x4C, // 0x50 39 | 0x48, 0x48, 0x4A, 0x4A, 0x48, 0x48, 0x4A, 0x4A, 40 | 0x35, 0x33, 0x1C, 0x1C, 0x34, 0x24, 0x1C, 0x1C, // 0x60 41 | 0x28, 0x28, 0x4B, 0x4B, 0x1F, 0x1F, 0x4B, 0x4B, 42 | 0x29, 0x20, 0x4C, 0x4C, 0x29, 0x20, 0x4C, 0x4C, // 0x70 43 | 0x48, 0x48, 0x4A, 0x4A, 0x48, 0x48, 0x4A, 0x4A, 44 | 0x43, 0x3F, 0x31, 0x31, 0x3B, 0x37, 0x31, 0x31, // 0x80 45 | 0x2B, 0x2B, 0x1D, 0x1D, 0x21, 0x21, 0x1D, 0x1D, 46 | 0x2F, 0x2D, 0x27, 0x27, 0x2F, 0x2D, 0x27, 0x27, // 0x90 47 | 0x1B, 0x1B, 0x49, 0x49, 0x1B, 0x1B, 0x49, 0x49, 48 | 0x41, 0x3D, 0x23, 0x23, 0x39, 0x25, 0x23, 0x23, // 0xA0 49 | 0x2B, 0x2B, 0x1D, 0x1D, 0x21, 0x21, 0x1D, 0x1D, 50 | 0x2E, 0x22, 0x1E, 0x1E, 0x2E, 0x22, 0x1E, 0x1E, // 0xB0 51 | 0x1B, 0x1B, 0x49, 0x49, 0x1B, 0x1B, 0x49, 0x49, 52 | 0x35, 0x33, 0x1C, 0x1C, 0x34, 0x24, 0x1C, 0x1C, // 0xC0 53 | 0x28, 0x28, 0x4B, 0x4B, 0x1F, 0x1F, 0x4B, 0x4B, 54 | 0x29, 0x20, 0x4C, 0x4C, 0x29, 0x20, 0x4C, 0x4C, // 0xD0 55 | 0x48, 0x48, 0x4A, 0x4A, 0x48, 0x48, 0x4A, 0x4A, 56 | 0x35, 0x33, 0x1C, 0x1C, 0x34, 0x24, 0x1C, 0x1C, // 0xE0 57 | 0x28, 0x28, 0x4B, 0x4B, 0x1F, 0x1F, 0x4B, 0x4B, 58 | 0x29, 0x20, 0x4C, 0x4C, 0x29, 0x20, 0x4C, 0x4C, // 0xF0 59 | 0x48, 0x48, 0x4A, 0x4A, 0x48, 0x48, 0x4A, 0x4A}; 60 | 61 | int magic(int x, int y) 62 | { 63 | static BYTE matrix[8][8] = { 64 | { 2, 0, 2, 1, 3, 0, 3, 1 } , 65 | { 3, 1, 0, 3, 2, 1, 0, 2 } , 66 | { 0, 2, 1, 2, 0, 3, 1, 3 } , 67 | { 1, 3, 0, 3, 1, 2, 0, 2 } , 68 | { 2, 0, 1, 2, 3, 0, 1, 3 } , 69 | { 3, 1, 3, 0, 2, 1, 2, 0 } , 70 | { 0, 2, 0, 1, 3, 0, 3, 2 } , 71 | { 1, 3, 0, 3, 2, 1, 2, 0 } }; 72 | 73 | return matrix[y % 8][x % 8]; 74 | } 75 | 76 | 77 | 78 | MBCMIF::MBCMIF () 79 | { 80 | /*int x, y; 81 | 82 | for (y = 0; y < MAX_TILE_COUNT; ++y) 83 | for (x = 0; x < MAX_TILE_COUNT; ++x) 84 | { 85 | aaCornerMap[x][y] = 0; 86 | aaCenterMap[x][y] = '@'; 87 | }*/ 88 | } 89 | 90 | void MBCMIF::GenerateMap(MBCMapImage& mi) 91 | { 92 | mi.cTilesX = nDimension; 93 | mi.cTilesY = nDimension; 94 | mi.nTileset = nTileset; 95 | strcpy(mi.szName, szName); 96 | 97 | int x, y; 98 | for (y = 0; y < nDimension ; ++y) 99 | for (x = 0; x < nDimension; ++x) 100 | mi.aaTiles[x][y] = FindTileFor(x, y); 101 | 102 | DefineEnergyPools(mi); 103 | DefineStartLocations(mi); 104 | MakeCraters(mi); 105 | } 106 | /* 107 | void MBCMIF::BuildCalibrationMap (void) 108 | { 109 | nVersion = 3; 110 | nDimension = 32; 111 | nTileset = 1; 112 | strcpy(szName, "Calibration"); 113 | 114 | int x, y; 115 | for (x = 0; x < 32; ++x) 116 | for (y = 0; y < 32; ++y) 117 | { 118 | aaCornerMap[x][y] = 0; 119 | aaCenterMap[x][y] = '.'; 120 | } 121 | 122 | aaCenterMap[0][0] = 'S'; 123 | aaCenterMap[2][0] = 'M'; 124 | aaCenterMap[4][0] = 'L'; 125 | 126 | aaCenterMap[7][7] = -1; 127 | aaCenterMap[23][7] = -1; 128 | aaCenterMap[7][23] = -1; 129 | aaCenterMap[23][23] = -1; 130 | } 131 | */ 132 | #ifndef MOONBASECONSOLE 133 | void MBCMIF::Read_MIF_File (FILE *pf) 134 | { 135 | int rc; 136 | char szSize[7]; 137 | 138 | // First line should always be the header 139 | rc = fscanf(pf, "MBCMIF%d", &nVersion); 140 | if (rc != 1) 141 | { 142 | fprintf(stderr, "ERROR: Bad file header. Header must start with MBCMIF. Now exiting.\n"); 143 | exit(-1); 144 | } 145 | 146 | // Second line should always be the size 147 | if (nVersion == 1 || nVersion == 2) 148 | { 149 | rc = fscanf(pf, "%6s", &szSize); 150 | // TODO: Check return code. 151 | 152 | if (!strcmp("SMALL", szSize)) 153 | nDimension = 32; 154 | else if (!strcmp("MEDIUM", szSize)) 155 | nDimension = 40; 156 | else if (!strcmp("LARGE", szSize)) 157 | nDimension = 48; 158 | else if (!strcmp("HUGE", szSize)) 159 | nDimension = 56; 160 | else if (!strcmp("SAI", szSize)) 161 | nDimension = 64; 162 | else if (!strcmp("MAX", szSize)) 163 | nDimension = 80; 164 | else 165 | { 166 | fprintf(stderr, "The size \"%s\" is unsupported.\n", szSize); 167 | exit(-1); 168 | } 169 | } 170 | else if (nVersion == 3) 171 | fscanf(pf, "%d", &nDimension); 172 | 173 | // Third and fourth lines aren't present in version one, they are the tileset and name in later versions. 174 | if (nVersion == 1) 175 | { 176 | nTileset = 1; 177 | strcpy(szName, "AutoGenerated"); 178 | } 179 | if (nVersion >= 2) 180 | { 181 | char ch; 182 | 183 | // Read the tileset number and skip to the end of the line. 184 | rc = fscanf(pf, "%d", &nTileset); 185 | fread(&ch, sizeof(char), 1, pf); 186 | while (ch != 0x0A && !feof(pf)) 187 | fread(&ch, sizeof(char), 1, pf); 188 | 189 | // Read the name, limiting it to 16 characters and consuming the rest of the line 190 | int i = 0; 191 | 192 | memset(szName, 0, 17); 193 | fread(&ch, sizeof(char), 1, pf); 194 | while (ch != 0x0A && ch != 0xD && i < 16) 195 | { 196 | szName[i++] = ch; 197 | fread(&ch, sizeof(char), 1, pf); 198 | } 199 | while (ch != 0x0A && !feof(pf)) 200 | fread(&ch, sizeof(char), 1, pf); 201 | szName[16] = '\0'; 202 | } 203 | 204 | // Read the actual map data 205 | int y; 206 | int x; 207 | char ch; 208 | 209 | // TODO: Make this more robust 210 | for (y = 0; y < nDimension; ++y) 211 | { 212 | int corner; 213 | 214 | for (x = 0; x < nDimension; ++x) 215 | { 216 | // Need to do it as two lines because we can't just scan one byte as a number with fscanf. 217 | fscanf(pf, "%d", &corner); 218 | aaCornerMap[x][y] = corner; 219 | } 220 | 221 | // Skip the linefeed left by the last line . 222 | fread(&ch, sizeof(char), 1, pf); 223 | while (0x0A != ch && !feof(pf)) 224 | fread(&ch, sizeof(char), 1, pf); 225 | for (x = 0; x < nDimension; ++x) 226 | { 227 | int nStartLocMask = -1; 228 | 229 | fread(&ch, sizeof(char), 1, pf); 230 | if (ch != ' ') 231 | if (ch >= '0' && ch <= '9') 232 | nStartLocMask = (ch - '0') * 16; 233 | else if (ch >= 'A' && ch <= 'F') 234 | nStartLocMask = (10 + ch - 'A') * 16; 235 | 236 | fread(&ch, sizeof(char), 1, pf); 237 | 238 | if (nStartLocMask > -1) 239 | { 240 | if (ch >= '0' && ch <= '9') 241 | nStartLocMask += ch - '0'; 242 | else if (ch >= 'A' && ch <= 'F') 243 | nStartLocMask += 10 + ch - 'A'; 244 | 245 | aaCenterMap[x][y] = -nStartLocMask; 246 | } 247 | else 248 | aaCenterMap[x][y] = ch; 249 | } 250 | } 251 | } 252 | #endif 253 | 254 | void MBCMIF::DefineStartLocations (MBCMapImage& mi) 255 | { 256 | int x, y; 257 | 258 | for (y = 0; y < nDimension ; ++y) 259 | for (x = 0; x < nDimension; ++x) 260 | { 261 | char ch = aaCenterMap[x][y]; 262 | 263 | if (ch < 0) 264 | { 265 | int i; 266 | ch = -ch; 267 | 268 | if (ch & 1) 269 | { 270 | // 4 player start 271 | i = 0; 272 | while (i < 4) 273 | { 274 | if (mi.apl4PLocs[i].xLoc == 0xFFFF) 275 | { 276 | mi.apl4PLocs[i].xLoc = x * 60; 277 | mi.apl4PLocs[i].yLoc = y * 60; 278 | break; 279 | } 280 | ++i; 281 | } 282 | } 283 | ch = ch >> 1; 284 | if (ch & 1) 285 | { 286 | // 3 player start 287 | i = 0; 288 | while (i < 3) 289 | { 290 | if (mi.apl3PLocs[i].xLoc == 0xFFFF) 291 | { 292 | mi.apl3PLocs[i].xLoc = x * 60; 293 | mi.apl3PLocs[i].yLoc = y * 60; 294 | break; 295 | } 296 | ++i; 297 | } 298 | } 299 | ch = ch >> 1; 300 | if (ch & 1) 301 | { 302 | // 2 player start 303 | i = 0; 304 | while (i < 2) 305 | { 306 | if (mi.apl2PLocs[i].xLoc == 0xFFFF) 307 | { 308 | mi.apl2PLocs[i].xLoc = x * 60; 309 | mi.apl2PLocs[i].yLoc = y * 60; 310 | break; 311 | } 312 | ++i; 313 | } 314 | } 315 | ch = ch >> 1; 316 | if (ch & 1) 317 | { 318 | // 2v2 player start 319 | i = 0; 320 | while (i < 4) 321 | { 322 | if (mi.apl2v2PLocs[i].xLoc == 0xFFFF) 323 | { 324 | mi.apl2v2PLocs[i].xLoc = x * 60; 325 | mi.apl2v2PLocs[i].yLoc = y * 60; 326 | break; 327 | } 328 | ++i; 329 | } 330 | } 331 | ch = ch >> 1; 332 | if (ch & 1) 333 | { 334 | // 1v3 player start 335 | i = 0; 336 | while (i < 4) 337 | { 338 | if (mi.apl1v3PLocs[i].xLoc == 0xFFFF) 339 | { 340 | mi.apl1v3PLocs[i].xLoc = x * 60; 341 | mi.apl1v3PLocs[i].yLoc = y * 60; 342 | break; 343 | } 344 | ++i; 345 | } 346 | } 347 | ch = ch >> 1; 348 | if (ch & 1) 349 | { 350 | // 1v2 player start 351 | i = 0; 352 | while (i < 3) 353 | { 354 | if (mi.apl1v2PLocs[i].xLoc == 0xFFFF) 355 | { 356 | mi.apl1v2PLocs[i].xLoc = x * 60; 357 | mi.apl1v2PLocs[i].yLoc = y * 60; 358 | break; 359 | } 360 | ++i; 361 | } 362 | } 363 | } 364 | } 365 | } 366 | 367 | void MBCMIF::DefineEnergyPools (MBCMapImage& mi) 368 | { 369 | int x, y; 370 | 371 | for (y = 0; y < nDimension ; ++y) 372 | for (x = 0; x < nDimension; ++x) 373 | { 374 | char ch = aaCenterMap[x][y]; 375 | 376 | if ('S' == ch || 'M' == ch || 'L' == ch) 377 | { 378 | // Verify legal position 379 | if (!((TLCorner(x,y) == TRCorner(x,y)) && (BLCorner(x,y) == BRCorner(x,y)) && 380 | (TLCorner(x,y) == BLCorner(x,y)) && (TRCorner(x,y) == BRCorner(x,y)))) 381 | throw CMapError(x, y, "small and medium energy pools must be on a flat tile"); 382 | 383 | if ('L' == ch) 384 | { 385 | BYTE nHeight; 386 | nHeight = BLCorner(x,y); 387 | if (!(TLCorner(x,y) == nHeight && TTLCorner(x,y) == nHeight && TTRCorner(x,y) == nHeight && TRCorner(x,y) == nHeight && BRCorner(x,y) == nHeight)) 388 | throw CMapError(x, y, "large energy pools must be on the lower of two flat tiles"); 389 | } 390 | 391 | int xLoc; 392 | int yLoc; 393 | 394 | if ('S' == ch) 395 | { 396 | xLoc = 60 * x + 30 + 20000; 397 | yLoc = 60 * y + 30; 398 | } 399 | else if ('M' == ch) 400 | { 401 | xLoc = 60 * x + 30 + 10000; 402 | yLoc = 60 * y + 30; 403 | } 404 | else 405 | { 406 | xLoc = 60 * x + 30; 407 | yLoc = 60 * y; 408 | } 409 | 410 | if (mi.cEnergyPools < 49) 411 | { 412 | mi.aepLocs[mi.cEnergyPools].plLocation.xLoc = xLoc; 413 | mi.aepLocs[mi.cEnergyPools].plLocation.yLoc = yLoc; 414 | 415 | ++mi.cEnergyPools; 416 | } 417 | else if (mi.cEnergyPools == 49) 418 | { 419 | mi.epLastPool.xLoc = xLoc; 420 | mi.epLastPool.yLoc = yLoc; 421 | 422 | ++mi.cEnergyPools; 423 | } 424 | else 425 | throw CMapError(x, y, "only 50 energy pools are allowed, this is the 51st"); 426 | } 427 | } 428 | } 429 | 430 | void MBCMIF::MakeCraters (MBCMapImage& mi) 431 | { 432 | //squarenumber, type, x, y (offset from top left (abs y)). x/y = 9 if none of that type 433 | BYTE locations[8][3][2] = {{ {1,1}, {5,2}, {3,5} }, 434 | { {6,1}, {1,6}, {2,0} }, 435 | { {0,4}, {3,2}, {6,5} }, 436 | { {4,4}, {5,0}, {9,9} }, 437 | { {3,6}, {9,9}, {2,1} }, 438 | { {9,9}, {3,3}, {0,2} }, 439 | { {2,4}, {0,0}, {5,3} }, 440 | { {4,1}, {0,3}, {5,6} } }; 441 | 442 | BYTE largegrid[10][10] = {{0,1,2,3,4,5,6,7,0,1}, // I made up the crater patterns for sizes larger than SAI 443 | {2,3,4,5,6,7,0,1,2,3}, // This will work for maps up to 80x80 444 | {4,5,6,7,0,1,2,3,4,5}, 445 | {3,0,1,2,6,4,5,7,3,0}, 446 | {1,2,3,4,5,6,7,0,1,2}, 447 | {3,4,5,6,7,0,1,2,3,4}, 448 | {6,3,0,1,2,7,4,5,6,3}, 449 | {5,6,7,0,1,2,3,4,5,6}, 450 | {0,1,2,3,4,5,6,7,0,1}, 451 | {2,3,4,5,6,7,0,1,2,3} }; 452 | 453 | for (int i = 0; i < nDimension / 8; i++) 454 | for (int j = 0; j < nDimension / 8; j++) 455 | for (int nCrater = 0; nCrater < 3; nCrater++) 456 | { 457 | if (9 == locations[largegrid[j][i]][nCrater][0]) 458 | continue; 459 | 460 | int x = locations[largegrid[j][i]][nCrater][0] + i * 8; 461 | int y = locations[largegrid[j][i]][nCrater][1] + j * 8; 462 | 463 | BYTE nLevel = TLCorner(x,y); 464 | if ( (TLCorner(x,y) == nLevel) && (TRCorner(x,y) == nLevel) && (TRRCorner(x,y) == nLevel) && 465 | (aaCenterMap[x][y] != 'W') && (aaCenterMap[x+1][y] != 'W') && 466 | (BLCorner(x,y) == nLevel) && (BRCorner(x,y) == nLevel) && (BRRCorner(x,y) == nLevel) && 467 | (aaCenterMap[x][y+1] != 'W') && (aaCenterMap[x+1][y+1] != 'W') && 468 | (BBLCorner(x,y) == nLevel) && (BBRCorner(x,y) == nLevel) && (BBRRCorner(x,y) == nLevel)) 469 | { 470 | // The tile values follow a predictable pattern, level one craters in order, etc. 471 | WORD nBase = 0xA6 + (TLCorner(x,y) * 12) + (nCrater * 4); 472 | 473 | mi.aaTiles[x] [y] = nBase; 474 | mi.aaTiles[x+1][y] = nBase + 1; 475 | mi.aaTiles[x] [y+1] = nBase + 2; 476 | mi.aaTiles[x+1][y+1] = nBase + 3; 477 | } 478 | } 479 | } 480 | 481 | 482 | WORD MBCMIF::FindTileFor (int x, int y) 483 | { 484 | int index; 485 | char ch; 486 | 487 | BYTE aLowBlanks[] = { 0x93, 0x94, 0x00, 0x96 }; 488 | BYTE aMedBlanks[] = { 0x97, 0x99, 0x0D, 0x9A }; 489 | BYTE aHiBlanks[] = { 0x9B, 0x9C, 0x1A, 0x9D }; 490 | ch = aaCenterMap[x][y]; 491 | if ('S' == ch || 'M' == ch || 'L' == ch || '.' == ch || ch < 0) 492 | { 493 | // Do the easy cases, things with no transitions. 494 | if (0 == TLCorner(x,y) && 0 == TRCorner(x,y) && 0 == BLCorner(x,y) && 0 == BRCorner(x,y)) 495 | return aLowBlanks[magic(x,y)]; 496 | // return 0x00; // Default blank low level 497 | // return aLevelOneBlankMap[y][x]; // TODO: Deal with partial special graphics and maps bigger than the template 498 | if (1 == TLCorner(x,y) && 1 == TRCorner(x,y) && 1 == BLCorner(x,y) && 1 == BRCorner(x,y)) 499 | return aMedBlanks[magic(x,y)]; 500 | // return 0x0D; // Default blank medium level 501 | if (2 == TLCorner(x,y) && 2 == TRCorner(x,y) && 2 == BLCorner(x,y) && 2 == BRCorner(x,y)) 502 | return aHiBlanks[magic(x,y)]; 503 | // return 0x1A; // Default blank high level 504 | 505 | // 506 | // Low to med transitions 507 | // 508 | if (0 == TLCorner(x,y) || 0 == TRCorner(x,y) || 0 == BLCorner(x,y) || 0 == BRCorner(x,y)) 509 | { 510 | // Corner cases 511 | 512 | int CornerSum = TLCorner(x,y) + TRCorner(x,y) + BLCorner(x,y) + BRCorner(x,y); 513 | 514 | if (1 == CornerSum) 515 | { 516 | if (TLCorner(x,y)) 517 | { 518 | if (TLLCorner(x,y) > 0 && TTLCorner(x,y) > 0) 519 | return 0x03; 520 | else 521 | return 0x89; 522 | } 523 | else if (TRCorner(x,y)) 524 | { 525 | if (TRRCorner(x,y) > 0 && TTRCorner(x,y) > 0) 526 | return 0x04; 527 | else 528 | return 0x8C; 529 | } 530 | else if (BLCorner(x,y)) 531 | { 532 | if (BLLCorner(x,y) > 0 && BBLCorner(x,y) > 0) 533 | return 0x02; 534 | else 535 | return 0x86; 536 | } 537 | else // BRCorner 538 | { 539 | if (BRRCorner(x,y) > 0 && BBRCorner(x,y) > 0) 540 | return 0x01; 541 | else 542 | return 0x83; 543 | } 544 | } 545 | 546 | // Straight edges 547 | 548 | // edge on bottom 549 | if (TLCorner(x,y) == 0 && TRCorner(x,y) == 0 && BLCorner(x,y) == 1 && BRCorner(x,y) == 1) 550 | { 551 | bool bLeftEased = (BLLCorner(x,y) == 0 && BBLCorner(x,y) == 1); 552 | bool bRightEased = (BRRCorner(x,y) == 0 && BBRCorner(x,y) == 1); 553 | 554 | if ( bLeftEased && bRightEased) 555 | return 0x0A; 556 | if (!bLeftEased && bRightEased) 557 | return 0x54; 558 | if ( bLeftEased && !bRightEased) 559 | return 0x55; 560 | if (!bLeftEased && !bRightEased) 561 | return (magic(x,y) & 0x01) ? 0x9F : 0x56; 562 | } 563 | // edge on top 564 | else if (TLCorner(x,y) == 1 && TRCorner(x,y) == 1 && BLCorner(x,y) == 0 && BRCorner(x,y) == 0) 565 | { 566 | bool bLeftEased = (TLLCorner(x,y) == 0 && TTLCorner(x,y) == 1); 567 | bool bRightEased = (TRRCorner(x,y) == 0 && TTRCorner(x,y) == 1); 568 | 569 | if ( bLeftEased && bRightEased) 570 | return 0x0C; 571 | if (!bLeftEased && bRightEased) 572 | return 0x52; 573 | if ( bLeftEased && !bRightEased) 574 | return 0x51; 575 | if (!bLeftEased && !bRightEased) 576 | return (magic(x,y) & 0x01) ? 0xA1 : 0x53; 577 | } 578 | // edge on right 579 | if (TLCorner(x,y) == 0 && BLCorner(x,y) == 0 && TRCorner(x,y) == 1 && BRCorner(x,y) == 1) 580 | { 581 | bool bTopEased = (TTRCorner(x,y) == 0 && TRRCorner(x,y) == 1); 582 | bool bBotEased = (BBRCorner(x,y) == 0 && BRRCorner(x,y) == 1); 583 | 584 | if ( bTopEased && bBotEased) 585 | return 0x09; 586 | if (!bTopEased && bBotEased) 587 | return 0x5B; 588 | if ( bTopEased && !bBotEased) 589 | return 0x5A; 590 | if (!bTopEased && !bBotEased) 591 | return (magic(x,y) & 0x01) ? 0x9E : 0x5C; 592 | } 593 | // edge on left 594 | if (TLCorner(x,y) == 1 && BLCorner(x,y) == 1 && TRCorner(x,y) == 0 && BRCorner(x,y) == 0) 595 | { 596 | bool bTopEased = (TTLCorner(x,y) == 0 && TLLCorner(x,y) == 1); 597 | bool bBotEased = (BBLCorner(x,y) == 0 && BLLCorner(x,y) == 1); 598 | 599 | if ( bTopEased && bBotEased) 600 | return 0x0B; 601 | if (!bTopEased && bBotEased) 602 | return 0x57; 603 | if ( bTopEased && !bBotEased) 604 | return 0x58; 605 | if (!bTopEased && !bBotEased) 606 | return (magic(x,y) & 0x01) ? 0xA0 : 0x59; 607 | } 608 | 609 | // Three corner cases 610 | 611 | // 0 1 1 1 0 0 0 0 0 0 612 | // 0 1 1 0x5F 0 1 1 0x5E 0 1 1 0x62 0 1 1 0x60 613 | // 0 0 0 0 0 0 0 1 1 1 614 | // 615 | // 0 1 1 1 0 0 1 0 0 1 616 | // 0 1 1 0x5D 0 1 1 0x06 0 1 1 0x61 0 1 1 0x07 617 | // 0 0 1 0 0 1 0 1 1 1 618 | // 619 | // 620 | // 0 0 0 1 0 0 1 0 1 1 621 | // 1 1 0 0x65 1 1 0 0x63 1 1 0 0x68 1 1 0 0x66 622 | // 1 0 1 0 0 0 0 0 0 0 623 | // 624 | // 0 0 0 1 0 0 1 0 1 1 625 | // 1 1 0 0x64 1 1 0 0x08 1 1 0 0x67 1 1 0 0x05 626 | // 1 1 1 1 1 0 0 1 0 0 627 | 628 | // corner in upper left 629 | if (BLCorner(x,y) == 1 && TLCorner(x,y) == 1 && TRCorner(x,y) == 1) 630 | { 631 | bool BLDiag = (BLLCorner(x,y) > 0 && BBLCorner(x,y) == 0); 632 | bool TRDiag = (TTRCorner(x,y) > 0 && TRRCorner(x,y) == 0); 633 | 634 | if (!BLDiag && !TRDiag) 635 | return 0x62; 636 | else if (!BLDiag && TRDiag) 637 | return 0x61; 638 | else if ( BLDiag && !TRDiag) 639 | return 0x60; 640 | else 641 | return 0x07; 642 | } 643 | 644 | // corner in upper right 645 | if (TLCorner(x,y) == 1 && TRCorner(x,y) == 1 && BRCorner(x,y) == 1) 646 | { 647 | bool TLDiag = (TTLCorner(x,y) > 0 && TLLCorner(x,y) == 0); 648 | bool BRDiag = (BRRCorner(x,y) > 0 && BBRCorner(x,y) == 0); 649 | 650 | if (!TLDiag && !BRDiag) 651 | return 0x65; 652 | else if (!TLDiag && BRDiag) 653 | return 0x64; 654 | else if ( TLDiag && !BRDiag) 655 | return 0x63; 656 | else 657 | return 0x08; 658 | } 659 | 660 | // corner in bottom right 661 | if (TRCorner(x,y) == 1 && BRCorner(x,y) == 1 && BLCorner(x,y) == 1) 662 | { 663 | bool TRDiag = (TRRCorner(x,y) > 0 && TTRCorner(x,y) == 0); 664 | bool BLDiag = (BBLCorner(x,y) > 0 && BLLCorner(x,y) == 0); 665 | 666 | if (!TRDiag && !BLDiag) 667 | return 0x68; 668 | else if (!TRDiag && BLDiag) 669 | return 0x67; 670 | else if ( TRDiag && !BLDiag) 671 | return 0x66; 672 | else 673 | return 0x05; 674 | } 675 | 676 | // corner in bottom left 677 | if (BRCorner(x,y) == 1 && BLCorner(x,y) == 1 && TLCorner(x,y) == 1) 678 | { 679 | bool TLDiag = (TLLCorner(x,y) > 0 && TTLCorner(x,y) == 0); 680 | bool BRDiag = (BBRCorner(x,y) > 0 && BRRCorner(x,y) == 0); 681 | 682 | if (!TLDiag && !BRDiag) 683 | return 0x5F; 684 | else if (!TLDiag && BRDiag) 685 | return 0x5D; 686 | else if ( TLDiag && !BRDiag) 687 | return 0x5E; 688 | else 689 | return 0x06; 690 | } 691 | 692 | // Opposing corner cases 693 | if (TLCorner(x,y) == 1 && BRCorner(x,y) == 1) 694 | { 695 | // There are four cases, big big, big small, small big, small small 696 | 697 | // big big 698 | if (TLLCorner(x,y) > 0 && TTLCorner(x,y) > 0 && BRRCorner(x,y) > 0 && BBRCorner(x,y) > 0) 699 | return 0x4D; 700 | // big small 701 | if (TLLCorner(x,y) > 0 && TTLCorner(x,y) > 0) 702 | return 0x81; 703 | // small big 704 | if (BRRCorner(x,y) > 0 && BBRCorner(x,y) > 0) 705 | return 0x82; 706 | // small small 707 | return 0x84; 708 | } 709 | if (TRCorner(x,y) == 1 && BLCorner(x,y) == 1) 710 | { 711 | // There are four cases, big big, big small, small big, small small 712 | 713 | // big big 714 | if (TRRCorner(x,y) > 0 && TTRCorner(x,y) > 0 && BLLCorner(x,y) > 0 && BBLCorner(x,y) > 0) 715 | return 0x4E; 716 | // big small 717 | if (TRRCorner(x,y) > 0 && TTRCorner(x,y) > 0) 718 | return 0x85; 719 | // small big 720 | if (BLLCorner(x,y) > 0 && BBLCorner(x,y) > 0) 721 | return 0x87; 722 | // small small 723 | return 0x88; 724 | } 725 | } 726 | 727 | // 728 | // Med to high transitions 729 | // 730 | if (1 == TLCorner(x,y) || 1 == TRCorner(x,y) || 1 == BLCorner(x,y) || 1 == BRCorner(x,y)) 731 | { 732 | // Corner cases 733 | 734 | int CornerSum = (TLCorner(x,y) == 2) + (TRCorner(x,y) == 2) + (BLCorner(x,y) == 2) + (BRCorner(x,y) == 2); 735 | 736 | if (1 == CornerSum) 737 | { 738 | if (TLCorner(x,y) == 2) 739 | { 740 | if (TLLCorner(x,y) == 2 && TTLCorner(x,y) == 2) 741 | return 0x10; 742 | else 743 | return 0x95; 744 | } 745 | else if (TRCorner(x,y) == 2) 746 | { 747 | if (TRRCorner(x,y) == 2 && TTRCorner(x,y) == 2) 748 | return 0x11; 749 | else 750 | return 0x98; 751 | } 752 | else if (BLCorner(x,y) == 2) 753 | { 754 | if (BLLCorner(x,y) == 2 && BBLCorner(x,y) == 2) 755 | return 0x0F; 756 | else 757 | return 0x92; 758 | } 759 | else // BRCorner 760 | { 761 | if (BRRCorner(x,y) == 2 && BBRCorner(x,y) == 2) 762 | return 0x0E; 763 | else 764 | return 0x8F; 765 | } 766 | } 767 | 768 | // Straight edges 769 | 770 | // edge on bottom 771 | if (TLCorner(x,y) < 2 && TRCorner(x,y) < 2 && BLCorner(x,y) == 2 && BRCorner(x,y) == 2) 772 | { 773 | bool bLeftEased = (BLLCorner(x,y) < 2 && BBLCorner(x,y) == 2); 774 | bool bRightEased = (BRRCorner(x,y) < 2 && BBRCorner(x,y) == 2); 775 | 776 | if ( bLeftEased && bRightEased) 777 | return 0x17; 778 | if (!bLeftEased && bRightEased) 779 | return 0x6C; 780 | if ( bLeftEased && !bRightEased) 781 | return 0x6D; 782 | if (!bLeftEased && !bRightEased) 783 | return (magic(x,y) & 0x01) ? 0xA3 : 0x6E; 784 | } 785 | // edge on top 786 | else if (TLCorner(x,y) == 2 && TRCorner(x,y) == 2 && BLCorner(x,y) < 2 && BRCorner(x,y) < 2) 787 | { 788 | bool bLeftEased = (TLLCorner(x,y) < 2 && TTLCorner(x,y) == 2); 789 | bool bRightEased = (TRRCorner(x,y) < 2 && TTRCorner(x,y) == 2); 790 | 791 | if ( bLeftEased && bRightEased) 792 | return 0x19; 793 | if (!bLeftEased && bRightEased) 794 | return 0x6A; 795 | if ( bLeftEased && !bRightEased) 796 | return 0x69; 797 | if (!bLeftEased && !bRightEased) 798 | return (magic(x,y) & 0x01) ? 0xA5 : 0x6B; 799 | } 800 | // edge on right 801 | if (TLCorner(x,y) < 2 && BLCorner(x,y) < 2 && TRCorner(x,y) == 2 && BRCorner(x,y) == 2) 802 | { 803 | bool bTopEased = (TTRCorner(x,y) < 2 && TRRCorner(x,y) == 2); 804 | bool bBotEased = (BBRCorner(x,y) < 2 && BRRCorner(x,y) == 2); 805 | 806 | if ( bTopEased && bBotEased) 807 | return 0x16; 808 | if (!bTopEased && bBotEased) 809 | return 0x73; 810 | if ( bTopEased && !bBotEased) 811 | return 0x72; 812 | if (!bTopEased && !bBotEased) 813 | return (magic(x,y) & 0x01) ? 0xA2 : 0x74; 814 | } 815 | // edge on left 816 | if (TLCorner(x,y) == 2 && BLCorner(x,y) == 2 && TRCorner(x,y) < 2 && BRCorner(x,y) < 2) 817 | { 818 | bool bTopEased = (TTLCorner(x,y) < 2 && TLLCorner(x,y) == 2); 819 | bool bBotEased = (BBLCorner(x,y) < 2 && BLLCorner(x,y) == 2); 820 | 821 | if ( bTopEased && bBotEased) 822 | return 0x18; 823 | if (!bTopEased && bBotEased) 824 | return 0x6F; 825 | if ( bTopEased && !bBotEased) 826 | return 0x70; 827 | if (!bTopEased && !bBotEased) 828 | return (magic(x,y) & 0x01) ? 0xA4 : 0x71; 829 | } 830 | 831 | // edge on bottom 832 | if (TLCorner(x,y) == 1 && TRCorner(x,y) == 1 && BLCorner(x,y) == 2 && BRCorner(x,y) == 2) 833 | { 834 | // no other high corners 835 | if (BLLCorner(x,y) < 2 && BRRCorner(x,y) < 2) 836 | return 0x17; 837 | // high corner on left 838 | if (BLLCorner(x,y) == 2 && BRRCorner(x,y) < 2) 839 | return 0x6C; 840 | // high corner on right 841 | if (BLLCorner(x,y) < 2 && BRRCorner(x,y) == 2) 842 | return 0x6D; 843 | // both neighbor corners high 844 | if (BLLCorner(x,y) == 2 && BRRCorner(x,y) == 2) 845 | return (magic(x,y) & 0x01) ? 0xA3 : 0x6E; 846 | } 847 | // edge on top 848 | else if (TLCorner(x,y) == 2 && TRCorner(x,y) == 2 && BLCorner(x,y) == 1 && BRCorner(x,y) == 1) 849 | { 850 | // no other high corners 851 | if (TLLCorner(x,y) < 2 && TRRCorner(x,y) < 2) 852 | return 0x19; 853 | // high corner on left 854 | if (TLLCorner(x,y) == 2 && TRRCorner(x,y) < 2) 855 | return 0x6A; 856 | // high corner on right 857 | if (TLLCorner(x,y) < 2 && TRRCorner(x,y) == 2) 858 | return 0x69; 859 | // both neighbor corners high 860 | if (TLLCorner(x,y) == 2 && TRRCorner(x,y) == 2) 861 | return (magic(x,y) & 0x01) ? 0xA5 : 0x6B; 862 | } 863 | // edge on right 864 | if (TLCorner(x,y) == 1 && BLCorner(x,y) == 1 && TRCorner(x,y) == 2 && BRCorner(x,y) == 2) 865 | { 866 | // no high neighbor corners 867 | if (TTRCorner(x,y) < 2 && BBRCorner(x,y) < 2) 868 | return 0x16; 869 | // high neighbor corner on top 870 | if (TTRCorner(x,y) == 2 && BBRCorner(x,y) < 2) 871 | return 0x73; 872 | // high neighbor corner on bottom 873 | if (TTRCorner(x,y) < 2 && BBRCorner(x,y) == 2) 874 | return 0x72; 875 | // both neighbor corners high 876 | if (TTRCorner(x,y) == 2 && BBRCorner(x,y) == 2) 877 | return (magic(x,y) & 0x01) ? 0xA2 : 0x74; 878 | } 879 | // edge on left 880 | if (TLCorner(x,y) == 2 && BLCorner(x,y) == 2 && TRCorner(x,y) == 1 && BRCorner(x,y) == 1) 881 | { 882 | // no high neighbor corners 883 | if (TTLCorner(x,y) < 2 && BBLCorner(x,y) < 2) 884 | return 0x18; 885 | // high neighbor corner on top 886 | if (TTLCorner(x,y) == 2 && BBLCorner(x,y) < 2) 887 | return 0x6F; 888 | // high neighbor corner on bottom 889 | if (TTLCorner(x,y) < 2 && BBLCorner(x,y) == 2) 890 | return 0x70; 891 | // both neighbor corners high 892 | if (TTLCorner(x,y) == 2 && BBLCorner(x,y) == 2) 893 | return (magic(x,y) & 0x01) ? 0xA4 : 0x71; 894 | } 895 | 896 | // Three corner cases 897 | 898 | // Three corner cases 899 | 900 | // 0 1 1 1 0 0 0 0 0 0 901 | // 0 1 1 0x77 0 1 1 0x76 0 1 1 0x7A 0 1 1 0x78 902 | // 0 0 0 0 0 0 0 1 1 1 903 | // 904 | // 0 1 1 1 0 0 1 0 0 1 905 | // 0 1 1 0x75 0 1 1 0x13 0 1 1 0x79 0 1 1 0x14 906 | // 0 0 1 0 0 1 0 1 1 1 907 | // 908 | // 909 | // 0 0 0 1 0 0 1 0 1 1 910 | // 1 1 0 0x7D 1 1 0 0x7B 1 1 0 0x80 1 1 0 0x7E 911 | // 1 0 1 0 0 0 0 0 0 0 912 | // 913 | // 0 0 0 1 0 0 1 0 1 1 914 | // 1 1 0 0x7C 1 1 0 0x15 1 1 0 0x7F 1 1 0 0x12 915 | // 1 1 1 1 1 0 0 1 0 0 916 | 917 | // corner in upper left 918 | if (BLCorner(x,y) == 2 && TLCorner(x,y) == 2 && TRCorner(x,y) == 2) 919 | { 920 | bool BLDiag = (BLLCorner(x,y) > 1 && BBLCorner(x,y) < 2); 921 | bool TRDiag = (TTRCorner(x,y) > 1 && TRRCorner(x,y) < 2); 922 | 923 | if (!BLDiag && !TRDiag) 924 | return 0x7A; 925 | else if (!BLDiag && TRDiag) 926 | return 0x79; 927 | else if ( BLDiag && !TRDiag) 928 | return 0x78; 929 | else 930 | return 0x14; 931 | } 932 | 933 | // corner in upper right 934 | if (TLCorner(x,y) == 2 && TRCorner(x,y) == 2 && BRCorner(x,y) == 2) 935 | { 936 | bool TLDiag = ((TTLCorner(x,y) > 1) && (TLLCorner(x,y) < 2)); 937 | bool BRDiag = ((BRRCorner(x,y) > 1) && (BBRCorner(x,y) < 2)); 938 | 939 | if (!TLDiag && !BRDiag) 940 | return 0x7D; 941 | else if (!TLDiag && BRDiag) 942 | return 0x7C; 943 | else if ( TLDiag && !BRDiag) 944 | return 0x7B; 945 | else 946 | return 0x15; 947 | } 948 | 949 | // corner in bottom right 950 | if (TRCorner(x,y) == 2 && BRCorner(x,y) == 2 && BLCorner(x,y) == 2) 951 | { 952 | bool TRDiag = (TRRCorner(x,y) > 1 && TTRCorner(x,y) < 2); 953 | bool BLDiag = (BBLCorner(x,y) > 1 && BLLCorner(x,y) < 2); 954 | 955 | if (!TRDiag && !BLDiag) 956 | return 0x80; 957 | else if (!TRDiag && BLDiag) 958 | return 0x7F; 959 | else if ( TRDiag && !BLDiag) 960 | return 0x7E; 961 | else 962 | return 0x12; 963 | } 964 | 965 | // corner in bottom left 966 | if (BRCorner(x,y) == 2 && BLCorner(x,y) == 2 && TLCorner(x,y) == 2) 967 | { 968 | bool TLDiag = (TLLCorner(x,y) > 1 && TTLCorner(x,y) < 2); 969 | bool BRDiag = (BBRCorner(x,y) > 1 && BRRCorner(x,y) < 2); 970 | 971 | if (!TLDiag && !BRDiag) 972 | return 0x77; 973 | else if (!TLDiag && BRDiag) 974 | return 0x75; 975 | else if ( TLDiag && !BRDiag) 976 | return 0x76; 977 | else 978 | return 0x13; 979 | } 980 | 981 | // Opposing corner cases 982 | if (TLCorner(x,y) == 2 && BRCorner(x,y) == 2) 983 | { 984 | // There are four cases, big big, big small, small big, small small 985 | 986 | // big big 987 | if (TLLCorner(x,y) == 2 && TTLCorner(x,y) == 2 && BRRCorner(x,y) == 2 && BBRCorner(x,y) == 2) 988 | return 0x4F; 989 | // big small 990 | if (TLLCorner(x,y) == 2 && TTLCorner(x,y) == 2) 991 | return 0x8A; 992 | // small big 993 | if (BRRCorner(x,y) == 2 && BBRCorner(x,y) == 2) 994 | return 0x8B; 995 | // small small 996 | return 0x8D; 997 | } 998 | if (TRCorner(x,y) == 2 && BLCorner(x,y) == 2) 999 | { 1000 | // There are four cases, big big, big small, small big, small small 1001 | 1002 | // big big 1003 | if (TRRCorner(x,y) == 2 && TTRCorner(x,y) == 2 && BLLCorner(x,y) == 2 && BBLCorner(x,y) == 2) 1004 | return 0x50; 1005 | // big small 1006 | if (TRRCorner(x,y) == 2 && TTRCorner(x,y) == 2) 1007 | return 0x8E; 1008 | // small big 1009 | if (BLLCorner(x,y) == 2 && BBLCorner(x,y) == 2) 1010 | return 0x90; 1011 | // small small 1012 | return 0x91; 1013 | } 1014 | } 1015 | 1016 | throw CMapError(x, y, "illegal corner height arrangement"); 1017 | } 1018 | else if ('W' == ch) 1019 | { 1020 | // Check to make sure that we're on ground level 1021 | if (TLCorner(x,y) > 0 || TRCorner(x,y) > 0 || BLCorner(x,y) > 0 || BRCorner(x,y) > 0) 1022 | throw CMapError(x, y, "water must be on a flat tile"); 1023 | 1024 | index = (('W' != TLCenter(x,y)) << 7) | 1025 | (('W' != TCenter(x,y)) << 6) | 1026 | (('W' != TRCenter(x,y)) << 5) | 1027 | (('W' != LCenter(x,y)) << 4) | 1028 | (('W' != RCenter(x,y)) << 3) | 1029 | (('W' != BLCenter(x,y)) << 2) | 1030 | (('W' != BCenter(x,y)) << 1) | 1031 | ('W' != BRCenter(x,y)); 1032 | 1033 | WORD nWaterTile = aWaterTileMapG[index]; 1034 | 1035 | if (0x44 == nWaterTile) 1036 | { 1037 | WORD aWaterBlanks[] = { 0x45, 0x46, 0x44, 0x47 }; 1038 | 1039 | nWaterTile = aWaterBlanks[magic(x,y)]; 1040 | } 1041 | 1042 | return nWaterTile; 1043 | } 1044 | else 1045 | throw CMapError(x, y, "illegal tile character"); 1046 | 1047 | throw CMapError(x, y, "unknown tile find error"); 1048 | } --------------------------------------------------------------------------------