Certainly! Below is a test case generator for the "Water Pipe Construction" problem:

```python
import random

def generate_test_case():
    n = random.randint(3, 100)  # Number of bases
    m = random.randint(2, 1000)  # Number of roads
    s = random.randint(1, n)  # Water source base
    g1, g2 = random.sample([i for i in range(1, n + 1) if i != s], 2)  # Two main bases

    roads = set()
    while len(roads) < m:
        b1, b2 = random.sample(range(1, n + 1), 2)
        c = random.randint(1, 1000)
        roads.add((b1, b2, c))
        
    return n, m, s, g1, g2, list(roads)

def tcgen():
    test_cases = []
    while True:
        n, m, s, g1, g2, roads = generate_test_case()
        
        if (n, m, s, g1, g2, roads) == (0, 0, 0, 0, 0, []):
            break
        
        test_cases.append({
            "n": n,
            "m": m,
            "s": s,
            "g1": g1,
            "g2": g2,
            "roads": roads
        })
        
        if random.random() < 0.1:  # Arbitrary condition to stop adding more test cases
            break
    
    return test_cases

# Example usage:
test_cases = tcgen()
for case in test_cases:
    print(f"{case['n']} {case['m']} {case['s']} {case['g1']} {case['g2']}")
    for road in case['roads']:
        print(f"{road[0]} {road[1]} {road[2]}")
    print("0 0 0 0 0")  # End of input
```

### Explanation:
1. **generate_test_case Function**: This function generates a single test case with:
    - `n`: A random number of bases between 3 and 100.
    - `m`: A random number of roads between 2 and 1000.
    - `s`: A random water source base.
    - `g1` and `g2`: Two distinct main bases.
    - `roads`: A set of unique roads where each road is represented by a tuple `(b1, b2, c)`.

2. **tcgen Function**: This function aggregates multiple test cases:
    - It continuously generates random test cases.
    - Each test case is added to `test_cases` list.
    - The loop breaks either by an arbitrary stopping condition (in this case, a random chance) or when a specific dummy input `(0, 0, 0, 0, 0)` is generated.

3. **Printing Test Cases**: Iterates through the generated test cases and prints them in the required format, including the termination line `0 0 0 0 0`.

You can adjust the loop condition and randomness to generate more or fewer test cases as needed. This script ensures that the constraints of the problem are respected and that the test cases are varied and comprehensive.