Moo

Date: 2020-01-07 02:58:55


Download


Moo is a computer adaption of the paper and pencil game Bulls and Cows, from over a century ago. You might remember Mastermind, the old board game that used colored pegs. It was designed by Mordechai Meirovitz, a telecommunications expert from Israel. Mastermind was first released in 1971 by Invicta Plastics, after the idea was rejected by leading game companies. The game sold over 50 million set in 80 countries, and was the most successful new game of the 1970s.

I use to love playing Mastermind. Bulls and Cows uses a numbered secret code instead of colors, so I think it lines up perfectly with my retro themed text only video games. The first computer game, also named Moo, was written by J. M. Grochow in 1970.

Rules

The computer creates a 4 digit code consisting of numbers 1 thru 9. You the player, must guess what the code is. To help you along, the computer will give an hints in the form of bulls and cows. A bull means you guessed the right number, in the right place. A cow is the right number in the wrong place. You won't know which digit the bulls and cows corrispond to.

Consider the following example. The computer creates the code 4135, and you guess 1234. You would get 1 bull for the 3, and 2 cows for the 4 and 1. So after you made your guess the board would look like this:

        M O O

+ - - - - - - - - - +
| * * * *           |
+ - - - - - - - - - +
| 1 2 3 4   B C C . |
| 0 0 0 0   . . . . |
| 0 0 0 0   . . . . |
| 0 0 0 0   . . . . |
| 0 0 0 0   . . . . |
| 0 0 0 0   . . . . |
| 0 0 0 0   . . . . |
| 0 0 0 0   . . . . |
| 0 0 0 0   . . . . |
| 0 0 0 0   . . . . |
| 0 0 0 0   . . . . |
| 0 0 0 0   . . . . |
| 0 0 0 0   . . . . |
| 0 0 0 0   . . . . |
+ - - - - - - - - - +
| ? ? ? ?           |
+ - - - - - - - - - +

       Guess 1

You get 14 guesses. If you don't get the code after the 14th guess, the computer will have pitty on you and show you what the code was.

Entering your guess

To enter a guess, type in your code, and press ENTER. Note that you can keep typing numbers, but your guess won't register until you hit that ENTER key.

Mastermind

If this game looks vaguely familiar, you are likely remembering the board game Mastermind. This game was also created in 1970 by Mordecai Meirowitz of Israeli, a postmaster and telecommunications expert. It had been rejected by leading game companies, but was picked up by Invicta Plastics, which restyled and renamed the game before releasing it in 1971. It sold over 50 million sets in 80 countries, which made it the most successful game of the 1970s.

Compiling

You can find build instructions in the README.md file.

Hi-res 80x24 text mode

Note that these next sections were also covered in my Memory post. So if you read it there, you can skip it here.

My previous games, Minefield and Robot Minefield both used 32x16 mode. This is a great mode, and very fast, but it doesn't let you do lower case letters, and you can't do colors. But really, they were just intermediate steps to build my text routines anyway.

The Color Computer 3 introduced a 80x24 hi-res text mode, which let's you have individual colors for each letter and background, as well as underline and blink modes.

In order to manipulate the text in this mode and not take a hit using the standard routines, is to write directly to the video memory. hi-res text is located at $6C000-$6DFFF. However, the 6809 (the Coco's CPU) can only address memory from $0000-$FFFF. $6C000 is way out of the accessable address space.

GIME MMU

Enter the GIME MMU. It maps 8K blocks of ram from outside of the 64K address space into the 64K address space.

For example, if you mapped $6C000-$6DFFF to $E000-$FDFF, when you write to address $E000, you are actually writing to physical memory at $6C000. You can map more then one block at a time.

To map the video memory at $6C000-$6DFFF (the hi-res text screen ram in the table above), to you update the appropriate MMU register and tell it to point to the memory page you want. So to map $6C000-$6DFFF to $E000-$FDFF, you find the MMU register that is associated wth the block of memory you want. In our example that is MMU register $FFA7. Then we set what page it should be mapped to. In our example, we want $6C000-$6DFFF so that is page $36. To put that into C code, it looks like this:

//Color Computer 3 only
#include "coco.h"

int main()
{
    initCoCoSupport();
    width(80);
    byte* hiresText = 0xE000;           //where text memory will be mapped
    byte* mmuReg = 0xFFA7;              //point to the mmu 
    byte previousPageValue = *mmuReg;   //remember what it was
    *mmuReg = 0x36;                     //point to the text page

    //now address 0xE000 points to 0x6C000
    *hiresText = 'a';                   //put a letter on screen

    //set MMU back to normal
    *mmuReg = previousPageValue;        

    waitkey(TRUE);

    return 0;
}

It's important to remember to put the MMU register back to normal if you plan to use any standard routines. You see me keeping track of what the value was near the top of the program, then put it back to that value at the end of the program. Notice also, I set it back before I call waitkey(TRUE).

To make it a little easier to use, I created a couple functions to do the job for me:

#define PAGE_HIRES_TEXT 0x36
#define MMU_REGISTER    0xFFA7
#define PAGE_ADDR       0xE000

void mapmmu() {
    previousPageValue = *((byte*)MMU_REGISTER);
    *((byte*)MMU_REGISTER) = PAGE_HIRES_TEXT;
}

void unmapmmu() {
    *((byte*)MMU_REGISTER) = previousPageValue;
}

Text and color

The hi-res text mode stores one byte for the character to display, and a second byte for the attribute of that character:

/*
 * Bit map 76543210
 * 7   Blink     (0x80)
 * 6   Underline (0x40)
 * 543 Forground 
 * 210 Background
 */
void setColor(byte fg, byte bg) {
    colorAttr = (colorAttr & 0xC0) + ((fg & 0x07) << 3) + (bg & 0x07);
}

Then I make use of a routine like this to display text. Notice that I write a byte for the character, then the second byte is the colorAttr.

void gotoxy(byte x, byte y) {
    cursorx = x;
    cursory = y;
}

void textout(const char* s) {
    mapmmu();
    byte* addr = (byte*)PAGE_ADDR + (cursory * 160 + cursorx*2);
    int len = strlen(s);
    for (int i = 0; i < len; ++i) {
        *addr = *(s + i);
        *(addr + 1) = colorAttr;
        addr += 2;
        cursorx++;
    }
    unmapmmu();
}


Copyright © 2025, Lee Patterson