In NetHack, COLNO and ROWNO are engine-wide C preprocessor macros (typically defining the maximum grid dimensions of a standard dungeon map, usually 80x21 or similar) [INDEX]. Because you removed #include "hack.h" from your shared Classes/ directory to isolate the targets, the compiler parsing Window.m no longer knows what these identifiers mean.
Since map boundaries are standard grid constants across NetHack 3.4 and 3.6, you can safely decouple this from the engine headers using one of two clean strategies.
Option A: Define Fallback Defaults (Fastest and Recommended)
If Window.m is just using COLNO and ROWNO as standard internal fallback sizes when allocating view arrays or viewport layouts, you can define safe local preprocessor overrides right at the top of Window.m.
Open Classes/Window.m and add these standard macro definitions right beneath your framework imports:
#import "Window.h"#import <UIKit/UIKit.h>
// Standard NetHack grid dimension definitions (fallback values)#ifndef COLNO#define COLNO 80#endif
#ifndef ROWNO#define ROWNO 22#endif
Why this works perfectly:
By wrapping them in #ifndef, your shared framework compiles cleanly on its own using the standard default numbers. When your version-specific subclasses inherit these windows later, they can override any size allocations dynamically if a future variant (like NetHack 5.0) happens to change the map boundary dimensions.
Option B: Pass Dimensions in via Initializer (Architecturally Pure)
If you prefer not to keep hardcoded numbers inside the shared UI, you should treat dimensions as dynamic arguments provided during window initialization.
- Modify Classes/Window.h to update the init signature:
- (instancetype)initWithType:(int)type maxWidth:(int)width maxHeight:(int)height;
- Update Classes/Window.m to assign the parameters directly:
- (instancetype)initWithType:(int)type maxWidth:(int)width maxHeight:(int)height {
self = [super init];
if (self) {
_windowType = type;
maxWidth = width;
maxHeight = height;
}
return self;
}
- Pass the Native Macros from winiphone.m:
When NetHack requests the window creation inside your engine target framework, pass the native COLNO and ROWNO constants directly down to the shared initialization sequence. Because winiphone.m compiles directly against hack.h, it can read the macros safely:
// Inside winiphone.m (Version-Specific Target)#include "hack.h" // Safe here!
winid iphone_create_nhwindow(int type) {
// Call your shared window manager, passing the native C dimensions dynamically
Window *w = [[Window alloc] initWithType:type maxWidth:COLNO maxHeight:ROWNO];
// ... store and register the window
return generated_id;
}
Recommendation
Go with Option A first. Adding the standard macro fallbacks directly to the top of Window.m takes seconds, leaves your existing window instantiations completely intact, and will immediately advance your GitHub Actions builder past these layout road-blocks.
Once you declare these fallback constants, these two undeclared identifier errors will completely disappear.
What next target file compilation block or linker message pops up in your GitHub Actions runner pipeline? If there are any final methods to adapt, let me know!
In NetHack, COLNO and ROWNO are engine-wide C preprocessor macros (typically defining the maximum grid dimensions of a standard dungeon map, usually 80x21 or similar) [INDEX]. Because you removed #include "hack.h" from your shared Classes/ directory to isolate the targets, the compiler parsing Window.m no longer knows what these identifiers mean.
Since map boundaries are standard grid constants across NetHack 3.4 and 3.6, you can safely decouple this from the engine headers using one of two clean strategies.
Option A: Define Fallback Defaults (Fastest and Recommended)
If Window.m is just using COLNO and ROWNO as standard internal fallback sizes when allocating view arrays or viewport layouts, you can define safe local preprocessor overrides right at the top of Window.m.
Open Classes/Window.m and add these standard macro definitions right beneath your framework imports:
#import "Window.h"#import <UIKit/UIKit.h>
// Standard NetHack grid dimension definitions (fallback values)#ifndef COLNO#define COLNO 80#endif
#ifndef ROWNO#define ROWNO 22#endif
Why this works perfectly:
By wrapping them in #ifndef, your shared framework compiles cleanly on its own using the standard default numbers. When your version-specific subclasses inherit these windows later, they can override any size allocations dynamically if a future variant (like NetHack 5.0) happens to change the map boundary dimensions.
Option B: Pass Dimensions in via Initializer (Architecturally Pure)
If you prefer not to keep hardcoded numbers inside the shared UI, you should treat dimensions as dynamic arguments provided during window initialization.
self = [super init];
if (self) {
_windowType = type;
maxWidth = width;
maxHeight = height;
}
return self;
}
When NetHack requests the window creation inside your engine target framework, pass the native COLNO and ROWNO constants directly down to the shared initialization sequence. Because winiphone.m compiles directly against hack.h, it can read the macros safely:
// Inside winiphone.m (Version-Specific Target)#include "hack.h" // Safe here!
winid iphone_create_nhwindow(int type) {
// Call your shared window manager, passing the native C dimensions dynamically
Window *w = [[Window alloc] initWithType:type maxWidth:COLNO maxHeight:ROWNO];
}
Recommendation
Go with Option A first. Adding the standard macro fallbacks directly to the top of Window.m takes seconds, leaves your existing window instantiations completely intact, and will immediately advance your GitHub Actions builder past these layout road-blocks.
Once you declare these fallback constants, these two undeclared identifier errors will completely disappear.
What next target file compilation block or linker message pops up in your GitHub Actions runner pipeline? If there are any final methods to adapt, let me know!