A Good Place to Work?

I’ve been a fan of Ben Horowitz for years, certainly of his success as an investor and businessman and definitely of his writing. I’ve quoted some of Ben’s past posts to others, found many of his themes to be fabulous food for thought, and always look forward to reading his blog. And I usually learn something from his writing.

Alas, not this time. It was quite a surprise to read his recent post, A Good Place to Work. There’s some discussion about it here, including a response by Ben (which makes me feel a little better, but not much).

Purely selfish of me (after all it’s his blog, he can say whatever he wants!), but I hope Ben decides to write another post to clearly explain the choices he made in A Good Place to Work. Up until this point I’ve been a believer in Ben as an authority on leadership and management, and I want to get my warm-and-fuzzy back.

Zynga Rolled Back the Clock 25 Years, and That’s a Good Thing

Dean’s latest DeanBeat is a well-written, sober little piece on Zynga right now. BTW, I don’t say it often enough, but Dean is one of our industry’s journalistic treasures — Dean, please do keep up the great work.

Anyway here’s a money quote:

Plenty of people hated what Zynga became, and they trashed not only Zynga but Facebook and all social companies. To these people, Zynga never did anything right. They never gave it credit for expanding the meaning of being a gamer to hundreds of millions of people. 

This is a point I’ve been trying to make with hardcore gamer and game developer friends for some time now. Don’t get me wrong: I absolutely, hands-down, for sure, hate most of Zynga’s games, as do most people I know who have self-identified as a “gamer” for the last 1-2 decades. Particularly the early stuff — all of the Ville games just plain suck for us gamer types who have been playing since the 80’s/90’s.

But take FarmVille and transport it to 1985 and we would have all been fans. Whether a launch title on NES, an arcade game or a PC game with shitty graphics, we would have played it, enjoyed it and perceived it as having real gaming value.

Of course we’re not in 1985, and we’ve had a lot of time to grow up on new and better gaming experiences, advances in design, hardware, play mechanics and so on. We’ve been happily following the evolution of video games with our minds, hearts, fingers and wallets for a while now — and to us Zynga games sputter instead of sparkle. Their game mechanics are very often like Joshua and Tic-Tac-Toe — winning moves are boring and so we just don’t play.

For others — many others, many millions of others — who haven’t grown up on video games like we have, most Zynga games have been a great introduction to gaming. Regardless of their original intent, Zynga ushered in a whole new crop of customers far more interested in playing games than they were just a few years ago. This is a really great thing and the timing was fortunate considering the downward spiral the traditional industry has been in for the last several years.

So thanks, Zynga. My friends and I hate most of your games. But we’re also glad you came to the party and started the clock ticking for millions of new players. We’re hoping you’ll create games in the future that will show all those new folks how much fun and awesome video games can be. And I bet you’ll show our snob-asses a few new tricks. Take all that IPO money and spend it on quality from here on out, won’t you?

Dennis, You’re Awesome

It’s just a Best Buy commercial, but it’s so cool to see Dennis Crowley for three full minutes talking about Foursquare, particularly the bit, around two and a half minutes in, about avoiding the haters. Respect, Dennis.

Game Developer Funding Events

This is the first post of an ongoing list of game developer funding events, to keep more explicit track of the frequency of non-traditional game-related funding (usually by VCs) that’s going on in the industry. I’m not including Kickstarter events at this point (would be too much of a timesuck) and the list is not meant to be definitive by any means — it’s just a few bits here and there that show up on my daily webtrek, which includes excellent resources like VentureBeat’s Deals Channel. The list is only for actual game developers or studios.

August 2012

Company: Innovative Leisure
Funding SourceHummer Winblad
Amount: Undisclosed Seed round
Summary: Seamus Blackley is “focused on building games for ‘the new arcade’ of iOS devices”. Team includes Ed Rotberg, creator of Battlezone; Owen Rubin, creator of Major Havoc and Space Duel; Rich Adam, creator of Gravitar and co-developer of Missile Command; Ed Logg, co-creator of Asteroids and Centipede; Dennis Koble, creator of Touch Me and Shooting Gallery; Tim Skelly, Cinematronics arcade game designer; and Bruce Merrit, creator of Black Widow. [Source: VentureBeat]

Company: Funium
Funding Source: Family Odyssey with participation from angel investors
Amount: $1.8m
Summary: Funium originally raised $1.2 million in 2011 to build Family Village, which became available in pilot mode in June 2012. [Source: VentureBeat]

July 2012

Company: Social Point
Funding SourceIdinvest Partners and other funds including BBVA and Nauta Capital
Amount: $7.4m
Summary: Founded in 2008. Several social games in the last 18 months including Social Empires, Social Wars and Dragon City. Over 15 million MAU as of June 2012. [Source: MarketWatch]

Company: Phoenix Guild
Funding Source: Unnamed VCs, YouWeb
Amount: $1.1m
Summary: Founder Jason Citron (of Aurora Feint fame) said, “It seems obvious to me that core gamers are moving from PCs to other devices and tablets,” and Phoenix Guild’s goal is to provide great core games on those new platforms. [Source: TUAW]

 

Critical Path

Critical Path is a video project recently announced by Artifact Studios. The website has a slew of interview snippets with many of the game industry’s best-known game developers and is worth checking out.

Supposedly the project will end up as a single documentary that combines all of the interviews into a film about gaming as a whole. Their tagline is, “Explore the art, philosophy, politics and psychology of video games with some of the medium’s most influential designers and visionaries”.

Clicking around on several of the interviews is a bit more of a snooze than I would’ve anticipated, but some are interesting. I hope the project doesn’t end up as an industry-congratulatory or “thoughtfully informative representation” type of piece. Hopefully they’ve gathered some informed opinions on the current chaos in the industry and how digital distribution and discovery (or lack thereof) are transforming everything.

Painting to Texture on iOS

Draw Something has continued to do very well in the App Store and now we’re seeing more derivatives — apps and games with basic painting and sketching capabilities. Last weekend I had some fun playing around with a basic painting setup, just to see how much brush (pun intended) I’d have to go through to get to the painting picnic.

On iOS, there are really only a couple of ways to implement a painting app — Quartz or OpenGL ES (there’s a nice little walk-through using Quartz here, and Apple put together a cool little OGL example called GLPaint here).

It should be relatively clear that the OGL approach is cleaner, more flexible and a bit faster. But while GLPaint is a nice place to start, it’s not very app- or engine-friendly in the context of a full-fledged OGL app. Since the point of GLPaint’s example code is demonstrate how to do basic painting, it has no need to consider the rest of your OGL surface’s render loop, nor does it concern itself with other important engine pieces, like your OGL redundancy state checker, sorting and synchronization issues between render and update calls, and most important, clearing the buffer.

That last bit really is most important because a nicely-performing painting app should never clear the buffer. Doing so will quickly slow things down to a slide-show. This should be obvious: In order to paint to the screen — whether you’re using GL_POINT_SPRITE_OES or rolling your own quads — you’ll need to draw a ton of sprites on-screen to get a continuous line of color and/or texture. If you clear every frame, you have to re-draw every frame, and voila, you’ll have molasses in less time than it takes to launch the simulator. If you don’t clear, you’re only drawing a handful of new sprites each frame.

The GLPaint example does this — it doesn’t clear the buffer. However in a real-world app, you must clear every frame in order for anything else — GUI elements/textures, mesh rendering, camera changes, etc. — to work. Hence the conundrum — you need a nice, normal clear/render loop but you also need a render-only call each time you want to paint.

Luckily there’s a straightforward solution: painting to a texture, then render that texture in your normal render loop. And setting up a texture to paint to is easy, by attaching it to an FBO. For example, a full-screen texture buffer:

- (GLenum) CreateRenderTexture
{
    m_texW = [[UIScreen mainScreen] bounds].size.width;
    m_texH = [[UIScreen mainScreen] bounds].size.height;

    glGenFramebuffers(1, &m_texFrameBuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, m_texFrameBuffer);

    glGenTextures(1, &m_texTexture);
    glBindTexture(GL_TEXTURE_2D, m_texTexture);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_texW, m_texH,
        0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
        GL_TEXTURE_2D, m_texTexture, 0);

    return glCheckFramebufferStatus(GL_FRAMEBUFFER);
}

From there it’s simply a matter of drawing to the texture and only clearing the texture when you need to, e.g., by calling a function like this:

- (void) StartTextureRender:(BOOL)clear color:(COLOR)color
{
    glBindFramebuffer(GL_FRAMEBUFFER, m_texFrameBuffer);
    if (clear)
    {
        glClearColor(color.r, color.g, color.b, color.a);
        glClear(GL_COLOR_BUFFER_BIT);
    }
    glViewport(0, 0, m_texW, m_texH);
    // setup ortho matrix, render and client states here...
}

One of the cool things about Draw Something is that it records and replays your drawing. This is relatively straightforward functionality to implement, and GLPaint kinda-sorta does it as a nice bonus. However their implementation is on the oddball side and a bit shy of more readable, that-makes-sense-to-me production code. A clearer way to implement it is to do a standard 2D lerp between the current touch (as you move your finger on the screen) and the last touch. Then record the time it took between finger-down and finger-up for playback later. For instance:

- (void) Draw:(float)x y:(float)y
{
    if (numVerts == MAX_PATH_VERTS) return;
    end         = Vec2(x, y);
    dist        = Vec2Dist(start, end);
    num         = (int)dist;
    if (num > 0)
    {
        startVert   = numVerts;
        numVerts    = MaxInt(numVerts + num, MAX_PATH_VERTS);
        for (int i = startVert; i < numVerts; i++)
        {
            Vec2Lerp(&verts[i], start, end, (i - startVert) / dist);
        }
        time += [Engine GetTimeElapsed];
    }
    start = end;
    [self DrawRender];
}

Below is the entire class (note that several of the vars are structs elsewhere in the engine, but you get the gist).

// INTERFACE
#define MAX_PATH_VERTS  20000
@interface Path : NSObject
{
@public
    VEC2            verts[MAX_PATH_VERTS];
    int             numVerts;
    int             startVert;
    VEC2            start;
    VEC2            end;
    VEC2            cur;
    Texture*        texture;
    COLOR           color;
    float           size;
    float           tick;
    float           time;
    int             num;
    float           dist;
    BOOL            replaying;
    int             vertCount;
    int             curVert;
    int             endVert;
}
@property (nonatomic, readwrite) BOOL replaying;
- (id)   initWithColorTextureSize:(COLOR)c texture:(Texture*)t size:(float)s;
- (void) DrawStart:(float)x y:(float)y;
- (void) Draw:(float)x y:(float)y;
- (BOOL) Replay;
- (void) ReplayStart;
@end

// IMPLEMENTATION
@implementation Path
@synthesize replaying;
- (id) initWithColorTextureSize:(COLOR)c texture:(Texture*)t size:(float)s
{
    if (!(self == [super init])) return nil;
    numVerts        = 0;
    texture         = t;
    color           = c;
    size            = s;
    return self;
}
- (void) DrawRender
{
    if (num > 0)
    {
        glEnablePointSprite(GL_TRUE, size);
        glSetTexture(texture.index);
        glSetColor(color.r, color.g, color.b, color.a);
        glSetVertexPointerEx(&verts[0], sizeof(VEC2), 2);
        glDrawArrays(GL_POINTS, startVert, num);
    }
}
- (void) DrawStart:(float)x y:(float)y
{
    if (numVerts == MAX_PATH_VERTS) return;
    verts[0]    = start = end = Vec2(x, y);
    numVerts    = num = 1;
    startVert   = 0;
    time        = 0;
    [self DrawRender];
}
- (void) Draw:(float)x y:(float)y
{
    if (numVerts == MAX_PATH_VERTS) return;
    end         = Vec2(x, y);
    dist        = Vec2Dist(start, end);
    num         = (int)dist;
    if (num > 0)
    {
        startVert   = numVerts;
        numVerts    = IEMaxInt(numVerts + num, MAX_PATH_VERTS);
        for (int i = startVert; i < numVerts; i++)
        {
            Vec2Lerp(&verts[i], start, end, (i - startVert) / dist);
        }
        time += [Engine GetTimeElapsed];
    }
    start = end;
    [self DrawRender];
}
- (BOOL) Replay
{
    if (replaying)
    {
        tick    = Max(tick + [Engine GetTimeElapsed], time);
        curVert = endVert;
        endVert = (int)Max(Lerp(0, numVerts, tick / time), numVerts);
        dist    = Vec2Dist(start, end);
        end     = verts[endVert];
        for (int i = startVert; i < endVert; i++)
        {
            Vec2Lerp(&verts[i], start, end, (i - startVert) / dist);
        }
        start = end;
        int count = MinInt(endVert - curVert, 1);
        if (count > 0)
        {
            glEnablePointSprite(GL_TRUE, size);
            glSetTexture(texture.index);
            glSetColor(color.r, color.g, color.b, color.a);
            glSetVertexPointerEx(&verts[0], sizeof(VEC2), 2);
            glDrawArrays(GL_POINTS, curVert, count);
        }
        replaying = (endVert != numVerts);
    }
    return replaying;
}
- (void) ReplayStart
{
    curVert   = 0;
    endVert   = 0;
    replaying = (curVert < numVerts);
    if (replaying)
    {
        tick  = 0;
        time  = Min(time, 0.001);
        start = verts[0];
        end   = verts[1];
    }
}
@end

An NSMutableArray of multiple instances of this class is kept by the caller; each instance is born on finger-down (where we set color, brush texture and size) and dies on finger-up. Replay is easy — essentially just a programmatic rendering of the verts that were previously recorded while iterating over the NSMutableArray, handled with a flag in the Render() function. Below is the basic idea.

- (void) TouchDown:(float)x y:(float)y
{
    if (curSize == -1) // we're erasing here
    {
        [Engine StartTextureRender:YES color:curBackColor];
    }
    else
    {
        [Engine StartTextureRender:NO color:curBackColor];
        curPath = [[Path alloc] initWithColorTextureSize:curColor
                                                 texture:curTexture
                                                    size:curSize];
        [paths addObject:curPath], [curPath release];
        [curPath DrawStart:x y:y];
    }
}
- (void) TouchMove:(float)x y:(float)y
{
    [Engine StartTextureRender:NO color:curBackColor];
    [curPath Draw:x y:y];
}
- (void) TouchUp:(float)x y:(float)y
{
    curPath = nil;
}
- (void) Render
{
    [Engine RenderToTexture];
    if (replaying)
    {
        [Engine StartTextureRender:NO color:curBackColor];
        if (![curPath Replay])
        {
            curPath = nil;
            for (Path* m in paths) { if (m.replaying) { curPath = m; break; } }
            replaying = (curPath != nil);
        }
    }
}

One of the cool things about using OGL for painting and sketching is that you can very easily change up the brush texture, for nice Photoshop-like texture brushes (care should be paid to how you setup the blending, however, due to pre-multiplied alpha on iOS). While it’s possible to do this with Quartz, it’s much easier to grok using OGL. And of course you can do silly/fun stuff like paint a background behind your 3D orc model (maybe there’s a game idea in there somewhere, hmm — ok, maybe not).

Racing to the Bottom in Flatland

Racing to the Bottom in Flatland

Like a lot of Americans, my wife and I love movies. I’d say we’re above average film consumers, due in no small part to my love of theatre and film from an early age, as well as her years as a performance artist documenting much of her work on video and/or film.

So a few years ago when we first signed up for streaming movies via NetFlix, we were excited. At the time we were renting a house with a Blockbuster less than a mile away and had plenty of DVD options for re-viewing, but the idea of thousands upon thousands of movies at our fingertips every month, for less than the price of a single DVD or a couple of movie tickets, had us salivating.

We wound up streaming fewer movies than we anticipated, and it was a reminder of the power of perceived value as well as a lesson on the deceptive nature of choice. After the first couple of months the routine degenerated into:

Wife, in the kitchen, working on some incredible dish for dinner (she’s a serious gourmet cook): “Honey, what do you want to watch?”
Me, on the sofa already, flipping through all the crap on cable: “Oh, I dunno. What are you in the mood for?”
Her: “How about something on Netflix?”
Me: “I’ll check.”
Her, five minutes later: “How’s it going?”
Me: “Well, say, are you in he mood for something in particular?”
Her: “Oh not really, whatever you’d like.”
Me: “Maybe a campy 80’s flick.”
Her: “Sure!”
Her, ten minutes later: “So, are you finding anything?”
Me: “Hmmm, well, there’s a bad Tom Cruise movie, nah, I’m not in the mood. How about Willow? Oh, wait we have that on DVD, right?”
Her: “I believe so, but anything’s fine for me. I could maybe go for a disaster movie.”
Me: “Ok, that’ll work.”
Her, 10 minutes later, dinner’s almost ready: “So are you finding something?”
Me: “Well I don’t know, not really. There are plenty of action and disaster flicks. What do you think about Woody Allen?”
Her: “That’s not exactly an action movie. But sure, ok. Anything’s fine at this point.”
Me: “Alrighty, let me just look a little more.”
Her: 15 minutes later, after one or two more rounds of Q&A: “Dinner’s ready. What are we watching?”
Me: “Yeah, hmmm. Nothing’s really jumping out at me. Why don’t we catch up on Stewart and Colbert instead?”

This was the script for many an evening until it dawned on me that I was horrible, like most people, at choosing from too many options. The movies were all right there. There was an image of a movie poster, a star rating, a description, more info on the film if I wanted to view it. It wasn’t difficult to decide but the number of choices, low cost and easy access made it impossibly difficult. And it was Flatland (double entendre intended) — the structure of the presentation was not designed to lead me to a decision, it was all there in a single dimension of indistinguishable value.

My realization was not novel — there are a ton of complex psychological, sociological and cultural fractures in the bedrock of choice, some of which are discussed in books like The Paradox of Choice, The Tipping Point and more recently, The Myth of Choice (which was, by the way, written by Kent Greenfield, who hails from my hometown in Kentucky and was a couple of years ahead of me in school. Kent is a brilliant thinker and the real deal).

Choice, and in particular the relationship between choice and value, can be so tricky. For example, I know that if have to get up off my arse, get in the car, drive to Blockbuster, browse physical shelves, pay several bucks for a movie, then bring it home with the understanding that I’d better return it tomorrow or be penalized, I’m going to damn well watch the movie, and probably enjoy (or hate) it more. I will value the movie more (even if I don’t like it), because I had to give more to get it.

Perhaps the most important thing about the physical store is that it’s not Flatland. There are plenty of cues in an intuitive 3D world guiding my decision. As I walk the aisles, glance at posters, watch previews on LCD screens, browse end-caps, consider specials, drill-down by category and alphabetical then read the backs of boxes, I am continually operating in a sort of risk/reward environment at a granular, unconscious level. I have to put physical and mental effort into finding a movie, but it (usually) doesn’t feel like work. There is a natural discovery mechanism in play.

In the digital/virtual world of Netflix, discovery is more complicated and less intuitive. My instincts are muddied by a 2D world of flat images in a layout that poorly mimics the real world. The trade-offs between effort, choice and value are less clear. In terms of risk/reward, I start out risking little as I navigate a Flatland of seemingly endless choices. As time goes on, I realize that time is what is at risk. Choices have less value to me. Quality (the reward) becomes more and more important in order to mitigate risk. But my choice, or expected choice, has less and less value the more I risk because the choices are all flatly presented without curation or authority. It’s almost recursive, and instead of a race to a top choice, it’s a race to the bottom. If I pick something, it’s because my need to see any movie now outweighs my desire to be delighted by a particular movie.

The same is true for non-traditional games — games that are delivered digitally and have no real world discovery process (aside from word-of-mouth). This is just about everything in gaming right now except for the big-budget, massive IP-holding holdouts, on consoles and some PC games, in the traditional retail space. Discovery is truly a Flatland, for all the same reasons as streaming videos. It’s a race to bottom in terms of choice, but perhaps even more interesting, content — the games themselves — have also been racing to the bottom.

Discovery is a huge problem in the industry right now. Because mobile devices and digital distribution have eclipsed the traditional retail game business, we’re struggling to understand it all – fundamentally because our game-playing customers have too many choices and, for all the reasons above, this causes the perceived value of the content to do down. But the kicker is this: lower perceived value results in lower profits, which in turn results in lower-quality content. It’s a race to the bottom.

Discovery has become the domain of companies with enough money to sell content in Flatland. Since there is little hierarchy or thoughtful segmentation at point of purchase (not said lightly, by the way, because this is a huge problem to overcome), it’s like going into the physical store with a row of titles a mile long, one end-cap and the “best-sellers” shelved within the first 20 feet. Few customers will walk a mile to discover something new; more important, the sheer size and number of titles devalues the entire shelf.

As noted in Jeremy Liew’s recent post, Discovery is the problem in gaming, game design is incrementally improving and we are starting to see bigger budgets and somewhat higher quality, while distribution continues to be easy (the rote barrier-to-entry is still low, and the industry is not competing on distribution). But as Jeremy indisputably states, the outcome of easy development and distribution has been a massive explosion in the number of games.

Can quality keep up with quantity? The industry competes on discovery, but it does so in Flatland. So its methods have inevitably involved larger and larger marketing and PR spends, bigger brand spending, internal and external cross-promotion, [over] extending IP and game re-skinning, and certainly paid acquisition. Since every one of these things require deeper pockets than most developers have, not surprisingly the industry has begun to consolidate into a network of discovery-focused “publishers”. This is not too different from the traditional industry except the emphasis is on the publishers’ ability to segment and cross-promote by increasing the size of their catalogs very, very quickly. This makes sense, since discovery at the platform distribution level is so ineffective (unlike a traditional retail store). Therefore a big catalog is critical to overcoming the inherent obstacles in Flatland.

For developers, this has resulted in an unprecedented lack of funds from a growing number of non-traditional publishers who simply don’t have the business model to finance development. This new breed of publisher is looking to plug content into their pipeline without the more traditional dose of production help,  putting most of the risk into the hands of the developers, who must figure out how to fund from other sources. In Flatland, they’re a better choice than being buried on the shelf a half-mile down the aisle, but the extra risk leads to cutting corners on quality. In the short-term at least, this means the quality curve will continue to look more like the rolling hills of Tuscany than a profile of Half Dome.

While the problem of discovery is thorny and there are no easy answers, at Kineplay we’re continuing to research the viability of location, specifically location-based and map-based discovery mechanisms for games, and we believe location (ironically, as a better, non-Flat virtual substitute for the real world) is a promising solution. Location also has the built-in benefit of enabling content to be re-skinned or re-themed based on physical coordinates, which is a way to differentiate extended content and might help bridge the gap between where we are now and high-quality gaming.

Whatever the solutions that present themselves over the next several years, the industry (and its customers) can’t keep racing to the bottom in a Flatland which, ironically, has no real bottom.

Augmented Kinectality

From Next at Microsoft, this is a must-see:

And this is an even muster see (the real-time custom emitter that tracks morphology, in particular, is super cool):

Google Quest for NES!

In what will surely be one of the most awesomest April Fools entries this year, let’s hear it for Google’s Google Maps 8-Bit for NES (mobile version available on Game Boy!). Make sure you check these out:

Statue of Liberty
Parthenon
Eiffel Tower
Buckingham Palace
Taj Mahal
The Pyramids at Giza
Colosseum
Area 51
Google HQ

Google if you’re listening — and I know you are because so many of you “read” this blog — leave Quest mode IN! Seriously, dudes — make this a better, sillier world. You have the power.

Happiness is a Choice

What a great post from Bronnie Ware, which prompted her to write a book, in which she lists the five most common regrets that terminally ill patients had on their way out of this world. “I wish that I let myself be happier” is the one I find most interesting. As Bronnie says:

 Many did not realise until the end that happiness is a choice. They had stayed stuck in old patterns and habits. The so-called ‘comfort’ of familiarity overflowed into their emotions, as well as their physical lives. Fear of change had them pretending to others, and to their selves, that they were content. When deep within, they longed to laugh properly and have silliness in their life again.

Play is such a important part of human existence. Like love and art and mathematics, it skips past culture and economics and politics. It slips through language barriers. It jumps over random bumps in the road. And fills us with silliness and wonder.

Page 5 of 7« First...34567